<template>
  <div class="playbook-execution-container">
    <!-- 星空背景 -->
    <div class="starry-background">
      <div class="stars"></div>
      <div class="stars2"></div>
      <div class="stars3"></div>
    </div>

    <!-- 页面标题 -->
    <div class="page-header glass-effect">
      <div class="header-content">
        <div class="title-section">
          <h1 class="page-title">
            <i class="fa fa-play-circle"></i>
            Playbook编辑执行
          </h1>
          <p class="page-subtitle">在线编辑和实时执行Ansible Playbook</p>
        </div>

      </div>
    </div>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 左侧编辑区 -->
      <div class="editor-panel glass-effect" :style="{ width: editorWidth + '%' }">
        <!-- 模式切换区 -->
        <div class="mode-switch-section">
          <el-radio-group v-model="editMode" @change="onModeChange" class="mode-switch">
            <el-radio-button label="online">
              <i class="fa fa-edit"></i>
              在线编辑
            </el-radio-button>
            <el-radio-button label="existing">
              <i class="fa fa-folder-open"></i>
              选择现有
            </el-radio-button>
          </el-radio-group>
        </div>

        <!-- 在线编辑模式 -->
        <div v-if="editMode === 'online'" class="online-mode">
          <!-- 调试信息 -->
          <div v-if="false" style="background: rgba(255,255,255,0.1); padding: 10px; margin: 10px 0; border-radius: 4px;">
            <p>凭据数量: {{ availableCredentials.length }}</p>
            <p>清单数量: {{ inventories.length }}</p>
            <p>加载状态: {{ loading }}</p>
          </div>

          <div class="config-section">
            <el-form inline class="config-form">
              <el-form-item label="主机清单:">
                <el-select
                  v-model="selectedInventory"
                  placeholder="选择主机清单"
                  class="inventory-select"
                  :loading="loading"
                >
                  <el-option
                    v-for="inv in inventories"
                    :key="inv.id"
                    :label="inv.name"
                    :value="inv.id"
                  >
                    <div class="inventory-option">
                      <i class="fa fa-list"></i>
                      <span>{{ inv.name }}</span>
                      <el-tag size="small" type="info">{{ inv.config_name || '未知环境' }}</el-tag>
                    </div>
                  </el-option>
                </el-select>
              </el-form-item>

              <el-form-item label="执行凭据:">
                <el-select
                  v-model="selectedCredential"
                  placeholder="选择凭据"
                  class="credential-select"
                  :loading="loading"
                >
                  <el-option
                    v-for="cred in availableCredentials"
                    :key="cred.id"
                    :label="`${cred.name} (${cred.credential_type_display})`"
                    :value="cred.id"
                  >
                    <div class="credential-option">
                      <i :class="getCredentialIcon(cred.credential_type)"></i>
                      <span>{{ cred.name }}</span>
                      <el-tag size="small" :type="getCredentialTagType(cred.credential_type)">
                        {{ cred.credential_type_display }}
                      </el-tag>
                    </div>
                  </el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </div>
        </div>

        <!-- 选择现有模式 -->
        <div v-if="editMode === 'existing'" class="existing-mode">
          <div class="config-section">
            <!-- 第一行：配置和主机 -->
            <el-form inline class="config-form">
              <el-form-item label="Ansible配置:">
                <el-select
                  v-model="selectedAnsibleConfig"
                  @change="onAnsibleConfigChange"
                  placeholder="选择Ansible配置"
                  class="config-select"
                  :loading="loading"
                  size="small"
                >
                  <el-option
                    v-for="config in ansibleConfigs"
                    :key="config.id"
                    :label="config.name"
                    :value="config.id"
                  >
                    <div class="config-option">
                      <i class="fa fa-cogs"></i>
                      <span>{{ config.name }}</span>
                      <el-tag size="small" :type="config.is_active ? 'success' : 'danger'">
                        {{ config.is_active ? '活跃' : '停用' }}
                      </el-tag>
                    </div>
                  </el-option>
                </el-select>
              </el-form-item>

              <el-form-item label="目标主机:">
                <el-select
                  v-model="selectedAnsibleHost"
                  @change="loadHostDirectories"
                  @click="onHostSelectClick"
                  placeholder="选择主机"
                  class="host-select"
                  :disabled="!selectedAnsibleConfig"
                  size="small"
                >
                  <el-option
                    v-for="host in ansibleHosts"
                    :key="host.id"
                    :label="`${host.hostname} (${host.private_ip})`"
                    :value="host.id"
                  >
                    <div class="host-option">
                      <i class="fa fa-server"></i>
                      <span>{{ host.hostname }}</span>
                      <el-tag size="small" :type="host.status === 'online' ? 'success' : 'danger'">
                        {{ host.status }}
                      </el-tag>
                    </div>
                  </el-option>
                </el-select>
              </el-form-item>
            </el-form>

            <!-- 第二行：清单和凭据 -->
            <el-form inline class="config-form">
              <el-form-item label="主机清单:">
                <el-select
                  v-model="selectedInventory"
                  placeholder="选择主机清单"
                  class="inventory-select"
                  :loading="loading"
                  size="small"
                >
                  <el-option
                    v-for="inv in inventories"
                    :key="inv.id"
                    :label="inv.name"
                    :value="inv.id"
                  >
                    <div class="inventory-option">
                      <i class="fa fa-list"></i>
                      <span>{{ inv.name }}</span>
                      <el-tag size="small" type="info">{{ inv.config_name || '未知环境' }}</el-tag>
                    </div>
                  </el-option>
                </el-select>
              </el-form-item>

              <el-form-item label="执行凭据:">
                <el-select
                  v-model="selectedCredential"
                  placeholder="选择凭据"
                  class="credential-select"
                  :loading="loading"
                  size="small"
                >
                  <el-option
                    v-for="cred in availableCredentials"
                    :key="cred.id"
                    :label="`${cred.name} (${cred.credential_type_display})`"
                    :value="cred.id"
                  >
                    <div class="credential-option">
                      <i :class="getCredentialIcon(cred.credential_type)"></i>
                      <span>{{ cred.name }}</span>
                      <el-tag size="small" :type="getCredentialTagType(cred.credential_type)">
                        {{ cred.credential_type_display }}
                      </el-tag>
                    </div>
                  </el-option>
                </el-select>
              </el-form-item>
            </el-form>
          </div>

        </div>



        <!-- 编辑器工具栏 -->
        <div class="editor-toolbar">
          <div class="toolbar-left">
            <span class="file-info">
              <i class="fa fa-file-code-o"></i>
              {{ editMode === 'online' ? 'main.yml' : (activeFile || 'playbook.yml') }}
            </span>
          </div>
          <div class="toolbar-right">
            <el-button
              @click="executePlaybook"
              :loading="executing"
              :disabled="!canExecute"
              class="glass-button add-button"
              size="small"
            >
              <i class="fa fa-play"></i>
              {{ executing ? '执行中...' : '执行' }}
            </el-button>
            <el-button @click="validatePlaybook" class="glass-button sync-button" :loading="validating" size="small">
              <i class="fa fa-check"></i>
              语法检查
            </el-button>
            <el-button @click="savePlaybook" class="glass-button export-button" :disabled="!activeFile" size="small">
              <i class="fa fa-save"></i>
              保存
            </el-button>
            <el-button @click="loadTemplate" class="glass-button import-button" size="small">
              <i class="fa fa-copy"></i>
              模板
            </el-button>

          </div>
        </div>

        <!-- Monaco编辑器 -->
        <div class="editor-container">
          <div ref="monacoEditor" class="monaco-editor"></div>
        </div>

        <!-- 编辑器状态栏 -->
        <div class="editor-status">
          <div class="status-left">
            <span>行: {{ cursorPosition.line }}, 列: {{ cursorPosition.column }}</span>
            <span class="separator">|</span>
            <span :class="['syntax-status', syntaxStatus.type]">
              <i :class="getSyntaxIcon(syntaxStatus.type)"></i>
              {{ syntaxStatus.message }}
            </span>
          </div>
          <div class="status-right">
            <span>{{ fileSize }}</span>
            <span class="separator">|</span>
            <span>YAML</span>
          </div>
        </div>
      </div>

      <!-- 分隔条 -->
      <div class="resizer" @mousedown="startResize"></div>

      <!-- 右侧终端区 -->
      <div class="terminal-panel glass-effect" :style="{ width: (100 - editorWidth) + '%' }">
        <!-- 终端标题栏 -->
        <div class="terminal-header">
          <div class="terminal-title">
            <i class="fa fa-terminal"></i>
            执行终端
            <span v-if="currentExecution" class="execution-status">
              <el-tag :type="getStatusColor(currentExecution.status)" size="small">
                {{ getStatusText(currentExecution.status) }}
              </el-tag>
            </span>
          </div>
          <div class="terminal-controls">
            <!-- 控制按钮 -->
            <el-button size="small" @click="pauseExecution" v-if="executing" class="glass-button sync-button">
              <i class="fa fa-pause"></i>
              暂停
            </el-button>
            <el-button size="small" @click="stopExecution" v-if="executing" class="glass-button smart-button">
              <i class="fa fa-stop"></i>
              停止
            </el-button>
            <el-button size="small" @click="clearTerminal" class="glass-button refresh-button">
              <i class="fa fa-trash"></i>
              清空
            </el-button>
            <el-button size="small" @click="copyOutput" class="glass-button import-button">
              <i class="fa fa-copy"></i>
              复制
            </el-button>
            <el-button size="small" @click="downloadLog" class="glass-button export-button">
              <i class="fa fa-download"></i>
              下载
            </el-button>
          </div>
        </div>

        <!-- 进度条 -->
        <div class="execution-progress" v-if="executing">
          <el-progress
            :percentage="executionProgress"
            :status="executionStatus"
            :stroke-width="6"
            class="progress-bar"
          />
          <div class="progress-info">
            <span class="current-task">{{ currentTask }}</span>
            <span class="execution-time">{{ executionTime }}</span>
          </div>
        </div>

        <!-- 终端输出 -->
        <div class="terminal-output" ref="terminalContainer">
          <div
            v-for="(line, index) in terminalLines"
            :key="index"
            :class="[
              'terminal-line',
              line.type,
              { 'clickable': line.clickable }
            ]"
            @click="line.clickable ? toggleTaskDetails(line.taskId) : null"
          >
            <span class="timestamp">{{ line.timestamp }}</span>
            <span class="content" v-html="formatTerminalLine(line.content)"></span>
            <span v-if="line.clickable" class="click-hint">
              <i class="fa fa-external-link"></i>
            </span>
          </div>

          <!-- 空状态 -->
          <div v-if="terminalLines.length === 0" class="terminal-empty">
            <i class="fa fa-terminal"></i>
            <p>等待执行Playbook...</p>
            <p class="hint">选择主机、凭据和Playbook文件后点击执行按钮</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- AWX风格任务详情对话框 -->
  <el-dialog
    v-model="taskDetailsVisible"
    :title="`任务执行详情 - ${currentTaskTitle}`"
    width="90%"
    :close-on-click-modal="false"
    class="task-details-dialog"
    top="5vh"
  >
    <div v-if="currentTaskDetails" class="task-details-content scrollable-content">
      <!-- 基本信息 -->
      <div class="detail-section">
        <h4>基本信息</h4>
        <div class="detail-item" v-if="currentTaskDetails.changed !== undefined">
          <strong>状态:</strong>
          <span :class="getStatusClass(currentTaskDetails)">
            {{ getTaskStatusText(currentTaskDetails) }}
          </span>
        </div>
        <div class="detail-item" v-if="currentTaskDetails.cmd">
          <strong>执行命令:</strong> {{ currentTaskDetails.cmd }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.rc !== undefined">
          <strong>返回码:</strong>
          <span :class="currentTaskDetails.rc === 0 ? 'success-text' : 'error-text'">
            {{ currentTaskDetails.rc }}
          </span>
        </div>
        <div class="detail-item" v-if="currentTaskDetails.delta">
          <strong>执行时间:</strong> {{ currentTaskDetails.delta }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.start">
          <strong>开始时间:</strong> {{ currentTaskDetails.start }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.end">
          <strong>结束时间:</strong> {{ currentTaskDetails.end }}
        </div>
      </div>

      <!-- 标准输出 -->
      <div class="detail-section" v-if="currentTaskDetails.stdout">
        <h4>标准输出</h4>
        <pre class="output-content">{{ currentTaskDetails.stdout }}</pre>
      </div>

      <!-- 标准输出行（优先显示） -->
      <div class="detail-section" v-if="currentTaskDetails.stdout_lines && currentTaskDetails.stdout_lines.length > 0">
        <h4>执行输出</h4>
        <div class="output-lines">
          <div v-for="(line, index) in currentTaskDetails.stdout_lines" :key="index" class="output-line">
            {{ line }}
          </div>
        </div>
      </div>

      <!-- 对于OK状态的任务，显示更多有用信息 -->
      <div class="detail-section" v-if="isOkStatus(currentTaskDetails)">
        <h4>执行结果</h4>
        <div class="detail-item">
          <div class="info-message">
            <i class="fa fa-check-circle success-icon"></i>
            <span>任务执行成功，没有发生变化</span>
          </div>
          <div class="result-explanation">
            <div class="explanation-title">详细说明：</div>
            <ul>
              <li v-for="(explanation, index) in getOkStatusExplanation(currentTaskDetails)" :key="index">
                {{ explanation }}
              </li>
            </ul>
          </div>
        </div>
      </div>



      <!-- 错误输出 -->
      <div class="detail-section" v-if="currentTaskDetails.stderr">
        <h4>错误输出</h4>
        <pre class="error-content">{{ currentTaskDetails.stderr }}</pre>
      </div>

      <!-- 文件操作信息（copy, file, template等模块） -->
      <div class="detail-section" v-if="isFileModule(currentTaskDetails)">
        <h4>文件操作详情</h4>
        <div class="detail-item" v-if="currentTaskDetails.state">
          <strong>文件状态:</strong> {{ getFileStateText(currentTaskDetails.state) }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.src">
          <strong>源文件:</strong> {{ currentTaskDetails.src }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.dest">
          <strong>目标文件:</strong> {{ currentTaskDetails.dest }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.path">
          <strong>文件路径:</strong> {{ currentTaskDetails.path }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.mode">
          <strong>文件权限:</strong> {{ currentTaskDetails.mode }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.owner">
          <strong>文件所有者:</strong> {{ currentTaskDetails.owner }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.group">
          <strong>文件组:</strong> {{ currentTaskDetails.group }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.size !== undefined">
          <strong>文件大小:</strong> {{ formatFileSize(currentTaskDetails.size) }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.checksum">
          <strong>校验和:</strong> {{ currentTaskDetails.checksum }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.backup_file">
          <strong>备份文件:</strong> {{ currentTaskDetails.backup_file }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.recurse !== undefined">
          <strong>递归操作:</strong> {{ currentTaskDetails.recurse ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.force !== undefined">
          <strong>强制覆盖:</strong> {{ currentTaskDetails.force ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.diff">
          <strong>文件差异:</strong>
          <pre class="output-content">{{ JSON.stringify(currentTaskDetails.diff, null, 2) }}</pre>
        </div>
      </div>

      <!-- 服务管理信息（service, systemd等模块） -->
      <div class="detail-section" v-if="isServiceModule(currentTaskDetails)">
        <h4>服务管理详情</h4>
        <div class="detail-item" v-if="currentTaskDetails.name">
          <strong>服务名称:</strong> {{ currentTaskDetails.name }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.state">
          <strong>期望状态:</strong> {{ getServiceStateText(currentTaskDetails.state) }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.status">
          <strong>当前状态:</strong> {{ getServiceStatusText(currentTaskDetails.status) }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.enabled !== undefined">
          <strong>开机启动:</strong> {{ currentTaskDetails.enabled ? '已启用' : '已禁用' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.daemon_reload !== undefined">
          <strong>重载守护进程:</strong> {{ currentTaskDetails.daemon_reload ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.masked !== undefined">
          <strong>服务屏蔽:</strong> {{ currentTaskDetails.masked ? '已屏蔽' : '未屏蔽' }}
        </div>
      </div>

      <!-- 包管理信息（yum, apt, pip等模块） -->
      <div class="detail-section" v-if="isPackageModule(currentTaskDetails)">
        <h4>包管理详情</h4>
        <div class="detail-item" v-if="currentTaskDetails.name">
          <strong>包名称:</strong> {{ currentTaskDetails.name }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.version">
          <strong>版本:</strong> {{ currentTaskDetails.version }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.state">
          <strong>包状态:</strong> {{ getPackageStateText(currentTaskDetails.state) }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.update_cache !== undefined">
          <strong>更新缓存:</strong> {{ currentTaskDetails.update_cache ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.autoremove !== undefined">
          <strong>自动移除:</strong> {{ currentTaskDetails.autoremove ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.allow_unauthenticated !== undefined">
          <strong>允许未认证:</strong> {{ currentTaskDetails.allow_unauthenticated ? '是' : '否' }}
        </div>
        <div v-if="currentTaskDetails.results && Array.isArray(currentTaskDetails.results)">
          <div v-for="(result, index) in currentTaskDetails.results" :key="index" class="detail-item">
            <strong>{{ result.name || `包 ${index + 1}` }}:</strong> {{ getPackageResultText(result) }}
          </div>
        </div>
      </div>

      <!-- 用户管理信息（user, group等模块） -->
      <div class="detail-section" v-if="isUserModule(currentTaskDetails)">
        <h4>用户管理详情</h4>
        <div class="detail-item" v-if="currentTaskDetails.name">
          <strong>用户名:</strong> {{ currentTaskDetails.name }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.state">
          <strong>用户状态:</strong> {{ getUserStateText(currentTaskDetails.state) }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.uid">
          <strong>用户ID:</strong> {{ currentTaskDetails.uid }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.gid">
          <strong>组ID:</strong> {{ currentTaskDetails.gid }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.home">
          <strong>家目录:</strong> {{ currentTaskDetails.home }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.shell">
          <strong>Shell:</strong> {{ currentTaskDetails.shell }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.system !== undefined">
          <strong>系统用户:</strong> {{ currentTaskDetails.system ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.create_home !== undefined">
          <strong>创建家目录:</strong> {{ currentTaskDetails.create_home ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.remove !== undefined">
          <strong>移除用户:</strong> {{ currentTaskDetails.remove ? '是' : '否' }}
        </div>
      </div>

      <!-- Git模块信息 -->
      <div class="detail-section" v-if="isGitModule(currentTaskDetails)">
        <h4>Git操作详情</h4>
        <div class="detail-item" v-if="currentTaskDetails.repo">
          <strong>仓库地址:</strong> {{ currentTaskDetails.repo }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.dest">
          <strong>目标目录:</strong> {{ currentTaskDetails.dest }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.version">
          <strong>版本/分支:</strong> {{ currentTaskDetails.version }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.before">
          <strong>操作前版本:</strong> {{ currentTaskDetails.before }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.after">
          <strong>操作后版本:</strong> {{ currentTaskDetails.after }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.force !== undefined">
          <strong>强制更新:</strong> {{ currentTaskDetails.force ? '是' : '否' }}
        </div>
      </div>

      <!-- 命令执行模块（command, shell, script等） -->
      <div class="detail-section" v-if="isCommandModule(currentTaskDetails)">
        <h4>命令执行详情</h4>
        <div class="detail-item" v-if="currentTaskDetails.cmd">
          <strong>执行命令:</strong> {{ currentTaskDetails.cmd }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.chdir">
          <strong>工作目录:</strong> {{ currentTaskDetails.chdir }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.creates">
          <strong>创建文件:</strong> {{ currentTaskDetails.creates }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.removes">
          <strong>移除文件:</strong> {{ currentTaskDetails.removes }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.warn !== undefined">
          <strong>显示警告:</strong> {{ currentTaskDetails.warn ? '是' : '否' }}
        </div>
      </div>

      <!-- 文本编辑模块（lineinfile, replace等） -->
      <div class="detail-section" v-if="isTextModule(currentTaskDetails)">
        <h4>文本编辑详情</h4>
        <div class="detail-item" v-if="currentTaskDetails.path">
          <strong>文件路径:</strong> {{ currentTaskDetails.path }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.line">
          <strong>文本行:</strong> {{ currentTaskDetails.line }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.regexp">
          <strong>正则表达式:</strong> {{ currentTaskDetails.regexp }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.state">
          <strong>操作状态:</strong> {{ getTextStateText(currentTaskDetails.state) }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.backup !== undefined">
          <strong>创建备份:</strong> {{ currentTaskDetails.backup ? '是' : '否' }}
        </div>
        <div class="detail-item" v-if="currentTaskDetails.create !== undefined">
          <strong>创建文件:</strong> {{ currentTaskDetails.create ? '是' : '否' }}
        </div>
      </div>

      <!-- 其他信息 -->
      <div class="detail-section" v-if="currentTaskDetails.msg">
        <h4>消息</h4>
        <div class="detail-item">{{ currentTaskDetails.msg }}</div>
      </div>

      <!-- 原始JSON数据 -->
      <div class="detail-section">
        <h4>原始数据</h4>
        <pre class="output-content">{{ JSON.stringify(currentTaskDetails, null, 2) }}</pre>
      </div>
    </div>

    <template #footer>
      <el-button @click="taskDetailsVisible = false" class="glass-button add-button">关闭</el-button>
    </template>
  </el-dialog>

  <!-- 目录选择弹窗 -->
  <el-dialog
    v-model="directoryDialogVisible"
    title="选择Playbook目录"
    width="60%"
    :before-close="handleDirectoryDialogClose"
    class="directory-dialog"
  >
    <div class="directory-browser">
      <!-- 当前路径显示 -->
      <div class="current-path">
        <div class="path-input-section">
          <div class="path-input-wrapper">
            <i class="fa fa-folder-open path-icon"></i>
            <el-input
              v-model="inputPath"
              @input="onPathInput"
              placeholder="输入路径，如 /etc/ansible"
              class="path-input"
              size="small"
            />
          </div>
        </div>
        <div class="path-actions">
          <el-button
            @click="goToParentDirectory"
            :disabled="!currentPath || currentPath === '/'"
            class="glass-button sync-button"
            size="small"
          >
            <i class="fa fa-arrow-up"></i>
            上级目录
          </el-button>
          <el-button
            @click="refreshCurrentDirectory"
            :loading="loadingDirectoryContent"
            class="glass-button refresh-button"
            size="small"
          >
            <i class="fa fa-refresh"></i>
            刷新
          </el-button>
        </div>
      </div>

      <!-- 目录内容 -->
      <div class="directory-content">
        <!-- 目录列表 -->
        <div class="directories-section" v-if="currentDirectories.length > 0">
          <h4 class="section-title">
            <i class="fa fa-folder"></i>
            目录
          </h4>
          <div class="directory-list">
            <div
              v-for="dir in currentDirectories"
              :key="dir.name"
              @click="enterDirectory(dir.name)"
              class="directory-item"
            >
              <i class="fa fa-folder"></i>
              <span>{{ dir.name }}</span>
              <i class="fa fa-chevron-right"></i>
            </div>
          </div>
        </div>

        <!-- YAML文件选择 -->
        <div class="files-section" v-if="yamlFiles.length > 0">
          <h4 class="section-title">
            <i class="fa fa-file-code-o"></i>
            Playbook文件 ({{ yamlFiles.length }} 个)
          </h4>
          <div class="yaml-file-selector">
            <el-select
              v-model="selectedYamlFile"
              placeholder="选择一个Playbook文件"
              class="yaml-select"
              @change="onYamlFileSelected"
            >
              <el-option
                v-for="file in yamlFiles"
                :key="file.name"
                :label="file.name"
                :value="file"
              >
                <div class="yaml-option">
                  <i class="fa fa-file-text"></i>
                  <span>{{ file.name }}</span>
                </div>
              </el-option>
            </el-select>
          </div>
        </div>

        <!-- 空状态 -->
        <div v-if="currentDirectories.length === 0 && currentFiles.length === 0 && !loadingDirectoryContent" class="empty-state">
          <i class="fa fa-folder-open"></i>
          <p>此目录为空或没有YAML文件</p>
        </div>

        <!-- 加载状态 -->
        <div v-if="loadingDirectoryContent" class="loading-state">
          <i class="fa fa-spinner fa-spin"></i>
          <p>正在加载目录内容...</p>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="dialog-footer">
        <el-button @click="directoryDialogVisible = false" class="glass-button refresh-button">
          <i class="fa fa-times"></i>
          取消
        </el-button>
        <el-button
          @click="loadSelectedFile"
          :disabled="!selectedFile"
          :loading="loadingFileContent"
          class="glass-button add-button"
        >
          <i class="fa fa-download"></i>
          {{ loadingFileContent ? '加载中...' : '加载文件' }}
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { onMounted, onUnmounted, reactive, ref, computed, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import * as monaco from 'monaco-editor'
// 导入YAML语言支持
import 'monaco-editor/esm/vs/basic-languages/yaml/yaml.contribution'
// 导入YAML解析库
import * as yaml from 'js-yaml'

// 配置Monaco环境 - 修复worker路径
window.MonacoEnvironment = {
  getWorkerUrl: function (moduleId, label) {
    // YAML使用通用编辑器worker，没有专门的yaml worker
    return new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url).href
  }
}
import { ansibleAPI } from '@/api/ansible'
import { hostAPI } from '@/api/host'
import { registerAnsibleInventoryLanguage, unregisterAnsibleInventoryLanguage } from '@/utils/ansible-language.js'
import { getDefaultPlaybookContent } from '@/utils/ansible-playbook-language.js'

const router = useRouter()

// 响应式数据
const loading = ref(false)
const executing = ref(false)
const validating = ref(false)


// 编辑器相关
const monacoEditor = ref<HTMLElement | null>(null)
const terminalContainer = ref<HTMLElement | null>(null)
let editorInstance: monaco.editor.IStandaloneCodeEditor | null = null
let completionProviderDisposable: any = null // 用于管理自动完成提供者
const editorWidth = ref(45) // 左侧编辑器宽度百分比
const activeFile = ref('')
const cursorPosition = ref({ line: 1, column: 1 })
const syntaxStatus = ref({ type: 'ready', message: '就绪' })
const fileSize = ref('0 B')

// 模式切换
const editMode = ref('online') // 'online' | 'existing'

// 在线编辑模式数据
const selectedCredential = ref<number | null>(null)
const selectedInventory = ref<number | null>(null)
const availableCredentials = ref<any[]>([])
const inventories = ref<any[]>([])

// 选择现有模式数据
const selectedAnsibleConfig = ref<number | null>(null)
const selectedAnsibleHost = ref<number | null>(null)
const ansibleConfigs = ref<any[]>([])
const ansibleHosts = ref<any[]>([])

// 目录选择弹窗数据
const directoryDialogVisible = ref(false)
const currentPath = ref('')
const inputPath = ref('') // 用户输入的路径
const lastSelectedPath = ref('') // 记录上次选择的路径
const currentDirectories = ref<any[]>([])
const currentFiles = ref<any[]>([])
const yamlFiles = ref<any[]>([])
const selectedFile = ref<any>(null)
const selectedYamlFile = ref<any>(null)
const loadingDirectoryContent = ref(false)
const loadingFileContent = ref(false)
const currentFilePath = ref('') // 存储当前文件的完整路径

// 通用数据
const playbookFiles = ref<any[]>([])

// 终端相关
const terminalLines = ref<any[]>([])
const currentExecution = ref<any | null>(null)
const executionProgress = ref(0)
const executionStatus = ref('')
const currentTask = ref('')
const executionTime = ref('')

// 编辑器就绪状态
const editorReady = ref(false)

// 计算属性
const editorContent = computed(() => {
  if (!editorReady.value || !editorInstance) {
    return ''
  }
  return editorInstance.getValue() || ''
})

const canExecute = computed(() => {
  const hasCredential = !!selectedCredential.value
  const hasInventory = !!selectedInventory.value

  if (editMode.value === 'online') {
    const hasContent = editorReady.value && !!editorContent.value?.trim()
    return hasCredential && hasInventory && hasContent
  } else {
    const hasConfig = !!selectedAnsibleConfig.value
    const hasHost = !!selectedAnsibleHost.value
    const hasFile = !!activeFile.value
    return hasCredential && hasInventory && hasConfig && hasHost && hasFile
  }
})

// 主机选项相关方法
const getCredentialIcon = (type: string) => {
  const icons = {
    'ssh_key': 'fa fa-key',
    'password': 'fa fa-lock',
    'vault': 'fa fa-shield'
  }
  return icons[type] || 'fa fa-question'
}

const getCredentialTagType = (type: string) => {
  const types = {
    'ssh_key': 'success',
    'password': 'warning',
    'vault': 'info'
  }
  return types[type] || 'info'
}

const getSyntaxIcon = (type: string) => {
  const icons = {
    'ready': 'fa fa-check-circle',
    'error': 'fa fa-exclamation-triangle',
    'warning': 'fa fa-exclamation-circle',
    'validating': 'fa fa-spinner fa-spin'
  }
  return icons[type] || 'fa fa-question'
}

const getStatusColor = (status: string) => {
  const colors = {
    'running': 'warning',
    'success': 'success',
    'failed': 'danger',
    'stopped': 'info'
  }
  return colors[status] || 'info'
}

const getStatusText = (status: string) => {
  const texts = {
    'running': '运行中',
    'success': '成功',
    'failed': '失败',
    'stopped': '已停止'
  }
  return texts[status] || '未知'
}

// 模式切换方法
const onModeChange = (mode: string) => {
  // 清空当前数据
  clearCurrentData()

  // 根据模式加载不同数据
  if (mode === 'online') {
    loadOnlineModeData()
  } else {
    loadExistingModeData()
  }
}

const clearCurrentData = () => {
  // 在线编辑模式保留默认文件，其他模式清空
  if (editMode.value !== 'online') {
    playbookFiles.value = []
    activeFile.value = ''
  }

  // 清空编辑器内容
  if (editorInstance) {
    editorInstance.setValue(getDefaultPlaybookContent())
  }
}

// 在线编辑模式数据加载
const loadOnlineModeData = async () => {
  try {
    loading.value = true

    const [credentialsResponse, inventoriesResponse, configsResponse] = await Promise.all([
      ansibleAPI.getCredentials(),
      ansibleAPI.getInventories(),
      ansibleAPI.getConfigs()
    ])

    console.log('凭据响应:', credentialsResponse)
    console.log('清单响应:', inventoriesResponse)
    console.log('配置响应:', configsResponse)

    // 修复数据路径 - API返回的是 {count, results} 格式
    availableCredentials.value = credentialsResponse.data.results || []
    inventories.value = inventoriesResponse.data.results || []
    ansibleConfigs.value = configsResponse.data.results || []

    console.log('加载的凭据:', availableCredentials.value)
    console.log('加载的清单:', inventories.value)
    console.log('加载的配置:', ansibleConfigs.value)

    // 在线编辑模式下创建默认的playbook文件
    if (playbookFiles.value.length === 0) {
      const defaultFile = {
        name: 'main.yml',
        path: 'main.yml',
        content: getDefaultPlaybookContent(),
        modified: false
      }
      playbookFiles.value = [defaultFile]
      activeFile.value = defaultFile.path

      // 设置编辑器内容
      if (editorInstance) {
        editorInstance.setValue(defaultFile.content)
      }
    }

  } catch (error) {
    console.error('加载在线编辑数据失败:', error)
    ElMessage.error('加载数据失败')
  } finally {
    loading.value = false
  }
}

// 选择现有模式数据加载
const loadExistingModeData = async () => {
  try {
    loading.value = true

    // 同时加载配置和凭据
    const [configsResponse, credentialsResponse] = await Promise.all([
      ansibleAPI.getConfigs(),
      ansibleAPI.getCredentials()
    ])

    console.log('配置响应:', configsResponse)
    console.log('凭据响应:', credentialsResponse)

    // 修复数据路径
    ansibleConfigs.value = configsResponse.data.results || []
    availableCredentials.value = credentialsResponse.data.results || []
    // inventory将在选择配置后加载

    console.log('加载的配置:', ansibleConfigs.value)
    console.log('加载的凭据:', availableCredentials.value)

  } catch (error) {
    console.error('加载选择现有数据失败:', error)
    ElMessage.error('加载数据失败')
  } finally {
    loading.value = false
  }
}

// 加载Ansible配置下的主机
const loadAnsibleHosts = async (configId: number) => {
  if (!configId) {
    console.log('configId为空，跳过加载主机')
    return
  }

  console.log('开始加载主机，configId:', configId)

  try {
    // 从Ansible配置获取其管理的主机列表
    const hostsResponse = await ansibleAPI.getConfigHosts(configId)
    console.log('Ansible配置主机API完整响应:', hostsResponse)
    console.log('响应数据结构:', hostsResponse.data)

    // 处理API响应
    let hosts = []
    if (hostsResponse.data.status === 'success') {
      hosts = hostsResponse.data.data || []
    } else {
      console.warn('获取主机失败:', hostsResponse.data.message)
      ElMessage.error(hostsResponse.data.message || '获取主机列表失败')
      return
    }

    ansibleHosts.value = hosts
    console.log('最终加载的主机数量:', hosts.length)
    console.log('主机列表:', hosts)

    // 清空之前的选择
    selectedAnsibleHost.value = null
    playbookFiles.value = []

    if (hosts.length === 0) {
      ElMessage.warning('该Ansible配置下没有找到可用的主机')
    } else {
      ElMessage.success(`成功加载 ${hosts.length} 个主机`)
    }

  } catch (error) {
    console.error('加载Ansible主机失败:', error)
    ElMessage.error('加载主机列表失败')
  }
}

// 根据选择的配置加载inventory列表
const loadInventoriesByConfig = async (configId: number) => {
  if (!configId) {
    inventories.value = []
    selectedInventory.value = null
    return
  }

  try {
    // 根据配置ID过滤inventory
    const response = await ansibleAPI.getInventories({ config_id: configId })
    inventories.value = response.data.results || []

    // 清空之前选择的inventory
    selectedInventory.value = null

    console.log('根据配置加载的清单:', inventories.value)
  } catch (error) {
    console.error('加载Inventory失败:', error)
    ElMessage.error('加载主机清单失败')
  }
}

// 当Ansible配置改变时的处理函数
const onAnsibleConfigChange = async (configId: number) => {
  console.log('Ansible配置改变:', configId)

  // 同时加载主机和inventory
  await Promise.all([
    loadAnsibleHosts(configId),
    loadInventoriesByConfig(configId)
  ])
}


// 主机选择后的处理
const loadHostDirectories = async (hostId: number) => {
  if (!hostId) return

  selectedAnsibleHost.value = hostId
  // 打开目录选择弹窗
  openDirectoryDialog()
}

// 主机选择框点击处理
const onHostSelectClick = () => {
  // 如果已经选择了主机，点击时直接打开弹窗
  if (selectedAnsibleHost.value) {
    openDirectoryDialog()
  }
}

// 打开目录选择弹窗
const openDirectoryDialog = () => {
  directoryDialogVisible.value = true
  selectedFile.value = null
  selectedYamlFile.value = null
  yamlFiles.value = []

  // 如果有上次选择的路径，从那里开始，否则从根目录开始
  const startPath = lastSelectedPath.value || '/'
  loadDirectoryContent(startPath)
}

// 加载目录内容
const loadDirectoryContent = async (path: string) => {
  if (!selectedAnsibleHost.value) return

  try {
    loadingDirectoryContent.value = true
    currentDirectories.value = []
    currentFiles.value = []

    // 调用API获取目录内容
    const response = await ansibleAPI.getDirectoryContent(selectedAnsibleHost.value, path)

    if (response.data.success) {
      currentPath.value = path
      inputPath.value = path // 同步输入框的值
      currentDirectories.value = response.data.directories || []
      currentFiles.value = response.data.files || []
      yamlFiles.value = response.data.yaml_files || []

      // 清空之前的选择
      selectedYamlFile.value = null
      selectedFile.value = null

      // 检查是否有YAML文件
      if (yamlFiles.value.length > 0) {
        ElMessage.success(`发现 ${yamlFiles.value.length} 个Playbook文件，请选择一个`)
      }
    } else {
      ElMessage.error(response.data.message || '加载目录内容失败')
    }
  } catch (error) {
    console.error('加载目录内容失败:', error)
    ElMessage.error('加载目录内容失败')
  } finally {
    loadingDirectoryContent.value = false
  }
}

// 进入子目录
const enterDirectory = (dirName: string) => {
  const newPath = currentPath.value === '/' ? `/${dirName}` : `${currentPath.value}/${dirName}`
  loadDirectoryContent(newPath)
}

// 导航到输入的路径
const navigateToPath = () => {
  if (!inputPath.value.trim()) {
    return
  }

  let targetPath = inputPath.value.trim()

  // 确保路径以 / 开头
  if (!targetPath.startsWith('/')) {
    targetPath = '/' + targetPath
  }

  // 移除末尾的 /（除非是根目录）
  if (targetPath !== '/' && targetPath.endsWith('/')) {
    targetPath = targetPath.slice(0, -1)
  }

  // 更新输入框的值
  inputPath.value = targetPath

  // 加载目录内容
  loadDirectoryContent(targetPath)
}

// 防抖定时器
let pathInputTimer: NodeJS.Timeout | null = null

// 输入路径时的处理（带防抖）
const onPathInput = () => {
  if (pathInputTimer) {
    clearTimeout(pathInputTimer)
  }

  pathInputTimer = setTimeout(() => {
    if (inputPath.value.trim() && inputPath.value.trim() !== currentPath.value) {
      navigateToPath()
    }
  }, 800) // 800ms 防抖延迟
}

// YAML文件选择处理
const onYamlFileSelected = async (file: any) => {
  selectedFile.value = file
  // 确保选择框显示正确的值
  selectedYamlFile.value = file
  console.log('选择的YAML文件:', file)

  // 自动加载选中的文件内容
  await loadSelectedFile()
}

// 返回上级目录
const goToParentDirectory = () => {
  if (!currentPath.value || currentPath.value === '/') return

  const pathParts = currentPath.value.split('/').filter(part => part)
  pathParts.pop()
  const parentPath = pathParts.length > 0 ? `/${pathParts.join('/')}` : '/'
  loadDirectoryContent(parentPath)
}

// 刷新当前目录
const refreshCurrentDirectory = () => {
  loadDirectoryContent(currentPath.value || '/')
}

// 选择文件
const selectFile = (file: any) => {
  selectedFile.value = file
}

// 加载选中的文件
const loadSelectedFile = async () => {
  if (!selectedFile.value || !selectedAnsibleHost.value) return

  try {
    loadingFileContent.value = true

    const filePath = currentPath.value === '/'
      ? `/${selectedFile.value.name}`
      : `${currentPath.value}/${selectedFile.value.name}`

    // 调用API获取文件内容
    const response = await ansibleAPI.getFileContent(selectedAnsibleHost.value, filePath)

    if (response.data.success) {
      // 将文件内容加载到编辑器
      if (editorInstance) {
        editorInstance.setValue(response.data.content)
      }

      // 设置当前活动文件和路径
      activeFile.value = selectedFile.value.name
      currentFilePath.value = filePath

      // 记录当前路径，下次打开时从这里开始
      lastSelectedPath.value = currentPath.value

      // 关闭弹窗
      directoryDialogVisible.value = false

      ElMessage.success(`文件 ${selectedFile.value.name} 加载成功`)
    } else {
      ElMessage.error(response.data.message || '加载文件内容失败')
    }
  } catch (error) {
    console.error('加载文件内容失败:', error)
    ElMessage.error('加载文件内容失败')
  } finally {
    loadingFileContent.value = false
  }
}

// 关闭目录选择弹窗
const handleDirectoryDialogClose = () => {
  directoryDialogVisible.value = false
  selectedFile.value = null
}

// 格式化文件大小
const formatFileSize = (bytes: number) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 初始数据加载（根据当前模式）
const loadInitialData = async () => {
  if (editMode.value === 'online') {
    await loadOnlineModeData()
  } else {
    await loadExistingModeData()
  }
}



// 编辑器相关方法
const initializeEditor = () => {
  if (!monacoEditor.value) {
    console.error('编辑器容器未找到', monacoEditor.value)
    return
  }

  console.log('初始化编辑器...', monacoEditor.value)

  // 如果编辑器已经存在，先清理
  if (editorInstance) {
    console.log('清理现有编辑器实例')
    editorInstance.dispose()
    editorInstance = null
  }

  // 清理之前的自动完成提供者
  if (completionProviderDisposable) {
    console.log('清理现有自动完成提供者')
    completionProviderDisposable.dispose()
    completionProviderDisposable = null
  }

  try {
    // 定义一个更好看的自定义主题
    monaco.editor.defineTheme('playbook-colorful', {
      base: 'vs-dark',
      inherit: true,
      rules: [
        // 注释 - 绿色斜体
        { token: 'comment', foreground: '6A9955', fontStyle: 'italic' },

        // YAML键名 - 亮蓝色粗体
        { token: 'key', foreground: '4FC1FF', fontStyle: 'bold' },
        { token: 'string.key', foreground: '4FC1FF', fontStyle: 'bold' },

        // 字符串值 - 橙色
        { token: 'string', foreground: 'CE9178' },
        { token: 'string.value', foreground: 'CE9178' },
        { token: 'string.quoted', foreground: 'CE9178' },

        // 数字 - 浅绿色
        { token: 'number', foreground: 'B5CEA8' },
        { token: 'number.float', foreground: 'B5CEA8' },

        // 布尔值和关键字 - 紫色粗体
        { token: 'keyword', foreground: 'C586C0', fontStyle: 'bold' },
        { token: 'constant.language', foreground: 'C586C0', fontStyle: 'bold' },

        // 特殊关键字 - 黄色粗体
        { token: 'type', foreground: 'DCDCAA', fontStyle: 'bold' },
        { token: 'entity.name.type', foreground: 'DCDCAA', fontStyle: 'bold' },

        // 变量 - 浅蓝色
        { token: 'variable', foreground: '9CDCFE' },
        { token: 'variable.other', foreground: '9CDCFE' },

        // 分隔符 - 白色
        { token: 'delimiter', foreground: 'D4D4D4' },
        { token: 'punctuation', foreground: 'D4D4D4' },

        // 标签 - 青色
        { token: 'tag', foreground: '4CDCD4', fontStyle: 'bold' },

        // 属性 - 浅黄色
        { token: 'attribute.name', foreground: 'F9E79F' },

        // 操作符 - 白色
        { token: 'operator', foreground: 'D4D4D4' }
      ],
      colors: {
        'editor.background': '#1E1E1E',
        'editor.foreground': '#D4D4D4',
        'editorSuggestWidget.background': '#252526',
        'editorSuggestWidget.border': '#454545',
        'editorSuggestWidget.foreground': '#CCCCCC'
      }
    })

    editorInstance = monaco.editor.create(monacoEditor.value, {
      value: getDefaultPlaybookContent(),
      language: 'yaml', // 使用内置YAML语言，高亮更明显
      theme: 'playbook-colorful', // 使用自定义主题
      fontSize: 14,
      lineNumbers: 'on',
      wordWrap: 'on',
      minimap: { enabled: false },
      automaticLayout: true,
      scrollBeyondLastLine: false,
      folding: true,
      renderWhitespace: 'boundary',
      // 智能提示配置
      quickSuggestions: true,
      suggestOnTriggerCharacters: true,
      acceptSuggestionOnCommitCharacter: true,
      acceptSuggestionOnEnter: 'on',
      wordBasedSuggestions: false, // 禁用基于单词的建议，避免重复
      suggest: {
        showWords: false, // 不显示单词建议
        showSnippets: true,
        showKeywords: false
      }
    })

    // 设置更明显的主题
    if (editorInstance) {
      // 使用自定义的彩色主题，语法高亮更明显
      monaco.editor.setTheme('playbook-colorful')
      console.log('已设置playbook-colorful主题')

      // 强制刷新编辑器
      editorInstance.layout()

      // 设置编辑器就绪状态
      editorReady.value = true
      console.log('编辑器初始化完成')
    }

    // 清理之前的自动完成提供者
    if (completionProviderDisposable) {
      completionProviderDisposable.dispose()
    }

    // 注册完整的Ansible智能提示
    completionProviderDisposable = monaco.languages.registerCompletionItemProvider('yaml', {
      provideCompletionItems: (model, position) => {
        const lineContent = model.getLineContent(position.lineNumber)
        const textBeforeCursor = lineContent.substring(0, position.column - 1)

        // 基础Playbook结构
        const playbookStructure = [
          { label: 'name', insertText: 'name: ', documentation: 'Task or play name' },
          { label: 'hosts', insertText: 'hosts: ', documentation: 'Target hosts or groups' },
          { label: 'tasks', insertText: 'tasks:\n  - ', documentation: 'List of tasks to execute' },
          { label: 'vars', insertText: 'vars:\n  ', documentation: 'Variables for this play' },
          { label: 'become', insertText: 'become: true', documentation: 'Run tasks with sudo privileges' },
          { label: 'become_user', insertText: 'become_user: ', documentation: 'User to become' },
          { label: 'gather_facts', insertText: 'gather_facts: ', documentation: 'Whether to gather facts' },
          { label: 'handlers', insertText: 'handlers:\n  - ', documentation: 'Event handlers' },
          { label: 'roles', insertText: 'roles:\n  - ', documentation: 'Roles to include' },
          { label: 'when', insertText: 'when: ', documentation: 'Conditional execution' },
          { label: 'with_items', insertText: 'with_items:\n  - ', documentation: 'Loop over items' },
          { label: 'notify', insertText: 'notify: ', documentation: 'Trigger handlers' },
          { label: 'tags', insertText: 'tags:\n  - ', documentation: 'Task tags' }
        ]

        // 常用Ansible模块
        const ansibleModules = [
          // 系统模块
          { label: 'shell', insertText: 'shell: ', documentation: 'Execute shell commands' },
          { label: 'command', insertText: 'command: ', documentation: 'Execute commands' },
          { label: 'script', insertText: 'script: ', documentation: 'Run local script on remote nodes' },
          { label: 'raw', insertText: 'raw: ', documentation: 'Execute raw SSH commands' },

          // 文件模块
          { label: 'copy', insertText: 'copy:\n  src: \n  dest: ', documentation: 'Copy files to remote locations' },
          { label: 'file', insertText: 'file:\n  path: \n  state: ', documentation: 'Manage files and directories' },
          { label: 'template', insertText: 'template:\n  src: \n  dest: ', documentation: 'Template files' },
          { label: 'lineinfile', insertText: 'lineinfile:\n  path: \n  line: ', documentation: 'Manage lines in files' },
          { label: 'replace', insertText: 'replace:\n  path: \n  regexp: \n  replace: ', documentation: 'Replace text in files' },
          { label: 'blockinfile', insertText: 'blockinfile:\n  path: \n  block: |', documentation: 'Insert/update/remove text blocks' },

          // 包管理
          { label: 'yum', insertText: 'yum:\n  name: \n  state: ', documentation: 'Manage packages with yum' },
          { label: 'apt', insertText: 'apt:\n  name: \n  state: ', documentation: 'Manage packages with apt' },
          { label: 'package', insertText: 'package:\n  name: \n  state: ', documentation: 'Generic package manager' },
          { label: 'pip', insertText: 'pip:\n  name: \n  state: ', documentation: 'Manage Python packages' },

          // 服务管理
          { label: 'service', insertText: 'service:\n  name: \n  state: ', documentation: 'Manage services' },
          { label: 'systemd', insertText: 'systemd:\n  name: \n  state: ', documentation: 'Manage systemd services' },

          // 用户管理
          { label: 'user', insertText: 'user:\n  name: \n  state: ', documentation: 'Manage user accounts' },
          { label: 'group', insertText: 'group:\n  name: \n  state: ', documentation: 'Manage groups' },

          // 网络模块
          { label: 'uri', insertText: 'uri:\n  url: \n  method: ', documentation: 'Make HTTP requests' },
          { label: 'get_url', insertText: 'get_url:\n  url: \n  dest: ', documentation: 'Download files from HTTP/HTTPS/FTP' },

          // Git模块
          { label: 'git', insertText: 'git:\n  repo: \n  dest: ', documentation: 'Deploy software from git repositories' },

          // 数据库模块
          { label: 'mysql_user', insertText: 'mysql_user:\n  name: \n  password: ', documentation: 'Manage MySQL users' },
          { label: 'mysql_db', insertText: 'mysql_db:\n  name: \n  state: ', documentation: 'Manage MySQL databases' },

          // Docker模块
          { label: 'docker_container', insertText: 'docker_container:\n  name: \n  image: ', documentation: 'Manage Docker containers' },
          { label: 'docker_image', insertText: 'docker_image:\n  name: \n  state: ', documentation: 'Manage Docker images' },

          // 调试模块
          { label: 'debug', insertText: 'debug:\n  msg: ', documentation: 'Print debug information' },
          { label: 'assert', insertText: 'assert:\n  that: ', documentation: 'Assert conditions' },
          { label: 'fail', insertText: 'fail:\n  msg: ', documentation: 'Fail with message' },

          // 条件和循环
          { label: 'set_fact', insertText: 'set_fact:\n  ', documentation: 'Set host facts' },
          { label: 'include_tasks', insertText: 'include_tasks: ', documentation: 'Include task files' },
          { label: 'import_tasks', insertText: 'import_tasks: ', documentation: 'Import task files' },
          { label: 'include_vars', insertText: 'include_vars: ', documentation: 'Include variables from files' }
        ]

        // 检查是否在输入state值 - 更宽松的匹配条件
        const stateValueSuggestions = []
        const currentLine = lineContent.trim()
        const isStateContext = textBeforeCursor.includes('state:') || currentLine.startsWith('state:')

        if (isStateContext) {
          console.log('检测到state上下文，当前行:', currentLine, '光标前文本:', textBeforeCursor)

          // 根据上下文判断模块类型并提供相应的state值
          const content = model.getValue()
          const lines = content.split('\n')
          const currentLineIndex = position.lineNumber - 1

          // 向上查找模块类型 - 扩大搜索范围
          let moduleType = ''
          for (let i = currentLineIndex; i >= Math.max(0, currentLineIndex - 10); i--) {
            const line = lines[i].trim()
            if (line.match(/^\s*file\s*:/)) {
              moduleType = 'file'
              break
            } else if (line.match(/^\s*service\s*:/)) {
              moduleType = 'service'
              break
            } else if (line.match(/^\s*(yum|apt|package)\s*:/)) {
              moduleType = 'package'
              break
            } else if (line.match(/^\s*user\s*:/)) {
              moduleType = 'user'
              break
            } else if (line.match(/^\s*lineinfile\s*:/)) {
              moduleType = 'lineinfile'
              break
            } else if (line.match(/^\s*copy\s*:/)) {
              moduleType = 'copy'
              break
            }
          }

          console.log('检测到的模块类型:', moduleType)

          // 根据模块类型提供state值
          if (moduleType === 'file') {
            stateValueSuggestions.push(
              { label: 'file', insertText: 'file', documentation: '确保是文件' },
              { label: 'directory', insertText: 'directory', documentation: '确保是目录' },
              { label: 'link', insertText: 'link', documentation: '创建软链接' },
              { label: 'hard', insertText: 'hard', documentation: '创建硬链接' },
              { label: 'touch', insertText: 'touch', documentation: '创建空文件' },
              { label: 'absent', insertText: 'absent', documentation: '删除文件/目录' }
            )
          } else if (moduleType === 'service') {
            stateValueSuggestions.push(
              { label: 'started', insertText: 'started', documentation: '启动服务' },
              { label: 'stopped', insertText: 'stopped', documentation: '停止服务' },
              { label: 'restarted', insertText: 'restarted', documentation: '重启服务' },
              { label: 'reloaded', insertText: 'reloaded', documentation: '重载服务配置' }
            )
          } else if (moduleType === 'package') {
            stateValueSuggestions.push(
              { label: 'present', insertText: 'present', documentation: '安装包' },
              { label: 'absent', insertText: 'absent', documentation: '卸载包' },
              { label: 'latest', insertText: 'latest', documentation: '安装最新版本' }
            )
          } else if (moduleType === 'user') {
            stateValueSuggestions.push(
              { label: 'present', insertText: 'present', documentation: '创建用户' },
              { label: 'absent', insertText: 'absent', documentation: '删除用户' }
            )
          } else if (moduleType === 'lineinfile') {
            stateValueSuggestions.push(
              { label: 'present', insertText: 'present', documentation: '添加行' },
              { label: 'absent', insertText: 'absent', documentation: '删除行' }
            )
          }
        }

        // 合并所有建议
        const allSuggestions = [...playbookStructure, ...ansibleModules, ...stateValueSuggestions].map(item => ({
          ...item,
          kind: monaco.languages.CompletionItemKind.Property,
          range: {
            startLineNumber: position.lineNumber,
            endLineNumber: position.lineNumber,
            startColumn: position.column - textBeforeCursor.split(/\s+/).pop().length,
            endColumn: position.column
          }
        }))

        return { suggestions: allSuggestions }
      }
    })

    console.log('编辑器创建成功，已注册YAML智能提示', editorInstance)

    // 监听光标位置变化
    editorInstance.onDidChangeCursorPosition((e) => {
      cursorPosition.value = {
        line: e.position.lineNumber,
        column: e.position.column
      }
    })

    // 监听内容变化
    editorInstance.onDidChangeModelContent(() => {
      markFileAsModified()
      updateFileSize()
      validateSyntaxDebounced()
    })

    // 强制刷新编辑器布局
    setTimeout(() => {
      if (editorInstance) {
        editorInstance.layout()
        console.log('编辑器布局已刷新')
      }
    }, 100)

  } catch (error) {
    console.error('编辑器创建失败:', error)
  }
}

// getDefaultPlaybookContent 现在从语言文件导入

const markFileAsModified = () => {
  if (activeFile.value) {
    const file = playbookFiles.value.find(f => f.path === activeFile.value)
    if (file) {
      file.modified = true
    }
  }
}

const updateFileSize = () => {
  if (editorInstance) {
    const content = editorInstance.getValue()
    const bytes = new Blob([content]).size
    fileSize.value = formatBytes(bytes)
  }
}

const formatBytes = (bytes: number) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 防抖的语法验证
let validateTimeout: NodeJS.Timeout | null = null
const validateSyntaxDebounced = () => {
  if (validateTimeout) {
    clearTimeout(validateTimeout)
  }
  validateTimeout = setTimeout(() => {
    validateSyntax()
  }, 1000)
}

const validateSyntax = () => {
  if (!editorInstance) return

  const content = editorInstance.getValue()
  if (!content.trim()) {
    syntaxStatus.value = { type: 'ready', message: '就绪' }
    return
  }

  try {
    // 使用js-yaml库进行语法检查
    try {
      yaml.load(content)
      syntaxStatus.value = { type: 'ready', message: '语法正确' }
    } catch (yamlError) {
      // 将技术性错误信息转换为用户友好的提示
      let friendlyMessage = '语法错误'
      const originalMsg = yamlError.message || ''

      if (originalMsg.includes('bad indentation')) {
        const lineMatch = originalMsg.match(/\((\d+):(\d+)\)/)
        const lineNum = lineMatch ? lineMatch[1] : '未知'
        friendlyMessage = `第${lineNum}行: 缩进错误，请检查空格数量`
      } else if (originalMsg.includes('expected') && originalMsg.includes('but found')) {
        const lineMatch = originalMsg.match(/\((\d+):(\d+)\)/)
        const lineNum = lineMatch ? lineMatch[1] : '未知'
        friendlyMessage = `第${lineNum}行: 语法格式错误，请检查冒号和空格`
      } else if (originalMsg.includes('duplicated mapping key')) {
        const lineMatch = originalMsg.match(/\((\d+):(\d+)\)/)
        const lineNum = lineMatch ? lineMatch[1] : '未知'
        friendlyMessage = `第${lineNum}行: 重复的键名`
      } else if (originalMsg.includes('mapping values are not allowed')) {
        const lineMatch = originalMsg.match(/\((\d+):(\d+)\)/)
        const lineNum = lineMatch ? lineMatch[1] : '未知'
        friendlyMessage = `第${lineNum}行: 键值对格式错误`
      } else if (originalMsg.includes('sequence entries are not allowed')) {
        const lineMatch = originalMsg.match(/\((\d+):(\d+)\)/)
        const lineNum = lineMatch ? lineMatch[1] : '未知'
        friendlyMessage = `第${lineNum}行: 列表项格式错误`
      } else {
        // 提取行号信息
        const lineMatch = originalMsg.match(/\((\d+):(\d+)\)/)
        if (lineMatch) {
          const lineNum = lineMatch[1]
          friendlyMessage = `第${lineNum}行: 语法错误，请检查格式`
        }
      }

      syntaxStatus.value = { type: 'error', message: friendlyMessage }
    }

  } catch (error) {
    syntaxStatus.value = { type: 'error', message: '语法检查失败' }
  }
}

const switchFile = async (file: any) => {
  if (!editorInstance) return

  // 保存当前文件的修改
  if (activeFile.value) {
    const currentFile = playbookFiles.value.find(f => f.path === activeFile.value)
    if (currentFile) {
      currentFile.content = editorInstance.getValue()
    }
  }

  // 加载新文件内容
  if (!file.content) {
    try {
      const hostId = editMode.value === 'online' ? null : selectedAnsibleHost.value
      if (hostId) {
        const response = await ansibleAPI.getPlaybookContent(hostId, file.path)
        file.content = response.data.content
      } else {
        // 在线编辑模式，使用默认内容
        file.content = getDefaultPlaybookContent()
      }
    } catch (error) {
      console.error('加载文件内容失败:', error)
      ElMessage.error('加载文件内容失败')
      return
    }
  }

  editorInstance.setValue(file.content)
  activeFile.value = file.path
  updateFileSize()
}

const closeFile = (targetName: string) => {
  const index = playbookFiles.value.findIndex(f => f.path === targetName)
  if (index > -1) {
    playbookFiles.value.splice(index, 1)

    // 如果关闭的是当前文件，切换到其他文件
    if (activeFile.value === targetName && playbookFiles.value.length > 0) {
      const newIndex = Math.min(index, playbookFiles.value.length - 1)
      activeFile.value = playbookFiles.value[newIndex].path
      switchFile(playbookFiles.value[newIndex])
    } else if (playbookFiles.value.length === 0) {
      activeFile.value = ''
      if (editorInstance) {
        editorInstance.setValue(getDefaultPlaybookContent())
      }
    }
  }
}

// 分隔条拖拽
let isResizing = false
const startResize = (e: MouseEvent) => {
  isResizing = true
  document.addEventListener('mousemove', handleResize)
  document.addEventListener('mouseup', stopResize)
  e.preventDefault()
}

const handleResize = (e: MouseEvent) => {
  if (!isResizing) return

  const container = document.querySelector('.main-content') as HTMLElement
  if (container) {
    const rect = container.getBoundingClientRect()
    const newWidth = ((e.clientX - rect.left) / rect.width) * 100

    // 限制宽度范围
    if (newWidth >= 30 && newWidth <= 70) {
      editorWidth.value = newWidth
    }
  }
}

const stopResize = () => {
  isResizing = false
  document.removeEventListener('mousemove', handleResize)
  document.removeEventListener('mouseup', stopResize)
}

// 执行相关方法
const executePlaybook = async () => {
  if (!canExecute.value) {
    ElMessage.warning('请完善执行配置和Playbook文件')
    return
  }

  executing.value = true
  clearTerminal()

  try {
    const playbookContent = editorInstance?.getValue() || ''

    // 显示友好的开始信息
    addTerminalLine('🚀 正在启动Ansible Playbook执行...', 'info')
    addTerminalLine('📋 任务执行状态: ✅ 成功 | ⚠️ 变更 | ❌ 失败', 'info')
    addTerminalLine('💡 点击黄色状态行可查看详细执行结果', 'info')

    // 统一使用run_playbook方法，构建请求参数
    let finalPlaybookContent = playbookContent

    if (editMode.value === 'existing') {
      // 选择现有模式：需要先读取文件内容
      if (!currentFilePath.value) {
        ElMessage.error('请先选择一个Playbook文件')
        return
      }

      try {
        const fileResponse = await ansibleAPI.getFileContent(selectedAnsibleHost.value, currentFilePath.value)
        if (fileResponse.data.success) {
          finalPlaybookContent = fileResponse.data.content
        } else {
          ElMessage.error('读取Playbook文件失败')
          return
        }
      } catch (error) {
        ElMessage.error('读取Playbook文件失败')
        return
      }
    }

    const requestData = {
      playbook_content: finalPlaybookContent,
      playbook_name: editMode.value === 'online' ? 'main.yml' : (activeFile.value || 'playbook.yml'),
      inventory_id: selectedInventory.value,
      credential_id: selectedCredential.value
    }

    console.log('=== 执行请求调试 ===')
    console.log('请求数据:', requestData)
    console.log('编辑模式:', editMode.value)
    console.log('当前文件路径:', currentFilePath.value)
    console.log('选择的清单:', selectedInventory.value)
    console.log('选择的凭据:', selectedCredential.value)
    console.log('Playbook内容长度:', finalPlaybookContent.length)

    const response = await ansibleAPI.runPlaybook(requestData)

    console.log('=== 执行响应调试 ===')
    console.log('完整响应:', response)
    console.log('响应数据:', response.data)
    console.log('job_id:', response.data?.job_id)
    console.log('data字段:', response.data?.data)
    console.log('data.job_id:', response.data?.data?.job_id)

    // 从正确的路径获取job_id
    const jobId = response.data?.data?.job_id
    console.log('最终job_id:', jobId)

    if (!jobId) {
      throw new Error('未能获取到job_id')
    }

    currentExecution.value = {
      id: jobId,
      status: 'running',
      startTime: new Date(),
      progress: 0,
      currentTask: '初始化...'
    }

    startExecutionPolling(jobId)

  } catch (error) {
    executing.value = false
    addTerminalLine(`❌ 执行失败: ${error.message}`, 'error')
    ElMessage.error('Playbook执行失败')
  }
}

// 轮询执行状态
const startExecutionPolling = (jobId: string) => {
  const startTime = Date.now()

  const pollInterval = setInterval(async () => {
    try {
      const response = await ansibleAPI.getJobStatus(jobId)
      const status = response.data

      // 更新执行信息
      if (currentExecution.value) {
        currentExecution.value.status = status.status
        currentExecution.value.progress = status.progress || 0
        currentExecution.value.currentTask = status.current_task || ''
      }

      executionProgress.value = status.progress || 0
      currentTask.value = status.current_task || ''

      // 更新执行时间
      const elapsed = Math.floor((Date.now() - startTime) / 1000)
      executionTime.value = formatDuration(elapsed)

      console.log('=== 状态轮询调试 ===')
      console.log('状态响应:', status)
      console.log('任务状态:', status.status)
      console.log('输出行数:', status.new_output?.length || 0)
      console.log('错误信息:', status.stderr)
      console.log('完整状态对象:', JSON.stringify(status, null, 2))

      // 显示完整的Ansible输出（真正的AWX风格）
      if (status.new_output && status.new_output.length > 0) {
        // 保留emoji提示信息，只清空非提示的输出
        if (!status.output_displayed) {
          // 保留开始的emoji提示信息
          const emojiLines = terminalLines.value.filter(line =>
            line.content.includes('🚀') || line.content.includes('📋') || line.content.includes('💡')
          )
          terminalLines.value = emojiLines
        }

        // 显示所有输出行，按类型着色
        status.new_output.forEach((line, index) => {
          let displayType = 'output'
          let isClickable = false
          let taskId = ''

          // 根据行类型设置样式
          switch (line.type) {
            case 'play':
              displayType = 'info'
              break
            case 'task':
              displayType = 'info'
              break
            case 'recap':
              displayType = 'info'
              break
            case 'ok':
              displayType = 'success' // 绿色
              isClickable = true
              taskId = `task-${index}`
              break
            case 'changed':
              displayType = 'warning' // 黄色
              isClickable = true
              taskId = `task-${index}`
              break
            case 'failed':
              displayType = 'error' // 红色
              isClickable = true
              taskId = `task-${index}`
              break
            case 'host_stats':
              displayType = 'info'
              break
            default:
              displayType = 'output'
          }

          // 添加行到终端
          if (isClickable && line.details) {
            addClickableTaskLine(line.content, displayType, taskId, line.details)
          } else {
            addTerminalLine(line.content, displayType)
          }
        })
      }

      // 检查是否完成
      if (status.status === 'success' || status.status === 'failed') {
        executing.value = false
        clearInterval(pollInterval)

        if (status.status === 'failed') {
          // 显示错误信息
          if (status.stderr) {
            addTerminalLine(`❌ 执行失败: ${status.stderr}`, 'error')
          }
          if (status.new_output && status.new_output.length === 0) {
            addTerminalLine('❌ 没有输出信息，可能是连接或配置问题', 'error')
          }
        }

        // 只显示简单的完成消息，不显示额外的统计信息
        ElMessage({
          type: status.status === 'success' ? 'success' : 'error',
          message: `Playbook执行${status.status === 'success' ? '成功' : '失败'}，耗时: ${formatDuration(elapsed)}`
        })
      }

    } catch (error) {
      console.error('轮询状态失败:', error)
      clearInterval(pollInterval)
      executing.value = false
    }
  }, 1000) // 每秒轮询一次
}

const formatDuration = (seconds: number) => {
  const mins = Math.floor(seconds / 60)
  const secs = seconds % 60
  return mins > 0 ? `${mins}分${secs}秒` : `${secs}秒`
}

// 终端相关方法
const addTerminalLine = (content: string, type: string = 'output') => {
  terminalLines.value.push({
    timestamp: new Date().toLocaleTimeString(),
    content,
    type
  })

  // 自动滚动到底部
  nextTick(() => {
    if (terminalContainer.value) {
      terminalContainer.value.scrollTop = terminalContainer.value.scrollHeight
    }
  })
}

// 添加可点击的任务行（AWX风格）
const addClickableTaskLine = (content: string, type: string = 'output', taskId: string, details?: any) => {
  terminalLines.value.push({
    timestamp: new Date().toLocaleTimeString(),
    content,
    type,
    clickable: true,
    taskId,
    details,
    expanded: false
  })

  // 自动滚动到底部
  nextTick(() => {
    if (terminalContainer.value) {
      terminalContainer.value.scrollTop = terminalContainer.value.scrollHeight
    }
  })
}

// AWX风格：弹窗显示任务详情
const toggleTaskDetails = (taskId: string) => {
  const taskLine = terminalLines.value.find(line => line.taskId === taskId)
  if (taskLine && taskLine.details) {
    // 显示详情对话框
    showTaskDetailsDialog(taskLine.details, taskId)
  }
}

// 任务详情对话框相关
const taskDetailsVisible = ref(false)
const currentTaskDetails = ref(null)
const currentTaskTitle = ref('')

const showTaskDetailsDialog = (details: any, taskId: string) => {
  currentTaskDetails.value = details
  currentTaskTitle.value = taskId.replace('task-', '主机执行结果 ')
  taskDetailsVisible.value = true
}

// 获取原始源文件路径
const getOriginalSrc = (details: any) => {
  if (!details) return null

  // 优先从invocation.module_args中获取原始参数
  if (details.invocation && details.invocation.module_args && details.invocation.module_args.src) {
    return details.invocation.module_args.src
  }

  // 如果没有invocation信息，则使用结果中的src（可能是临时路径）
  if (details.src) {
    // 如果是临时文件路径，尝试提取文件名
    if (details.src.includes('ansible-tmp-') && details.src.includes('.source')) {
      return '(临时文件) ' + details.src.split('/').pop()
    }
    return details.src
  }

  return null
}

// 模块类型判断函数
const isFileModule = (details: any) => {
  return details && (details.dest || details.src || details.path || details.checksum || details.backup_file)
}

const isServiceModule = (details: any) => {
  return details && details.name && (details.state || details.status || details.enabled !== undefined)
}

const isPackageModule = (details: any) => {
  return details && (details.name || details.results) && (details.state || details.version)
}

const isUserModule = (details: any) => {
  return details && details.name && (details.uid || details.gid || details.home || details.shell)
}

const isOkStatus = (details: any) => {
  return details && details.changed === false && details.failed !== true
}

// 获取OK状态任务的详细说明
const getOkStatusExplanation = (details: any) => {
  const explanations = []

  if (isFileModule(details)) {
    if (details.state === 'directory') {
      explanations.push('目录已存在且权限正确')
    } else if (details.state === 'file') {
      explanations.push('文件已存在且内容、权限正确')
    } else if (details.state === 'absent') {
      explanations.push('文件/目录已确认不存在')
    } else {
      explanations.push('文件状态已符合预期')
    }

    if (details.mode) {
      explanations.push(`权限已设置为 ${details.mode}`)
    }
    if (details.owner) {
      explanations.push(`所有者已设置为 ${details.owner}`)
    }
  }

  if (isServiceModule(details)) {
    if (details.state === 'started') {
      explanations.push('服务已在运行状态')
    } else if (details.state === 'stopped') {
      explanations.push('服务已停止')
    } else if (details.state === 'restarted') {
      explanations.push('服务无需重启')
    }

    if (details.enabled === true) {
      explanations.push('服务已设置为开机启动')
    } else if (details.enabled === false) {
      explanations.push('服务已禁用开机启动')
    }
  }

  if (isPackageModule(details)) {
    if (details.state === 'present' || details.state === 'installed') {
      explanations.push('软件包已安装且版本正确')
    } else if (details.state === 'absent') {
      explanations.push('软件包已确认未安装')
    } else if (details.state === 'latest') {
      explanations.push('软件包已是最新版本')
    }
  }

  if (isUserModule(details)) {
    if (details.state === 'present') {
      explanations.push('用户已存在且配置正确')
    } else if (details.state === 'absent') {
      explanations.push('用户已确认不存在')
    }

    if (details.home) {
      explanations.push(`家目录已设置为 ${details.home}`)
    }
    if (details.shell) {
      explanations.push(`Shell已设置为 ${details.shell}`)
    }
  }

  // 如果没有特定的说明，提供通用说明
  if (explanations.length === 0) {
    explanations.push('任务执行成功，目标状态已达成')
    explanations.push('系统配置符合预期，无需进行任何更改')
  }

  return explanations
}

const isGitModule = (details: any) => {
  return details && (details.repo || details.before || details.after)
}

const isCommandModule = (details: any) => {
  return details && (details.cmd || details.command || details.script)
}

const isTextModule = (details: any) => {
  return details && (details.line || details.regexp) && details.path
}

// 文本转换函数
const getFileStateText = (state: string) => {
  const stateMap = {
    'file': '文件',
    'directory': '目录',
    'link': '软链接',
    'hard': '硬链接',
    'touch': '创建空文件',
    'absent': '删除',
    'present': '存在'
  }
  return stateMap[state] || state
}

const getServiceStateText = (state: string) => {
  const stateMap = {
    'started': '启动',
    'stopped': '停止',
    'restarted': '重启',
    'reloaded': '重载',
    'enabled': '启用',
    'disabled': '禁用'
  }
  return stateMap[state] || state
}

const getServiceStatusText = (status: string) => {
  const statusMap = {
    'active': '活跃',
    'inactive': '非活跃',
    'failed': '失败',
    'running': '运行中',
    'stopped': '已停止',
    'enabled': '已启用',
    'disabled': '已禁用'
  }
  return statusMap[status] || status
}

const getPackageStateText = (state: string) => {
  const stateMap = {
    'present': '安装',
    'absent': '卸载',
    'latest': '最新版本',
    'installed': '已安装',
    'removed': '已移除',
    'purged': '完全清除',
    'build-dep': '构建依赖',
    'fixed': '修复'
  }
  return stateMap[state] || state
}

const getUserStateText = (state: string) => {
  const stateMap = {
    'present': '创建',
    'absent': '删除'
  }
  return stateMap[state] || state
}

const getPackageResultText = (result: any) => {
  if (result.msg) return result.msg
  if (result.state) return getPackageStateText(result.state)
  return '已处理'
}

const getTextStateText = (state: string) => {
  const stateMap = {
    'present': '添加行',
    'absent': '删除行'
  }
  return stateMap[state] || state
}

// 获取任务状态文本
const getTaskStatusText = (details: any) => {
  // 优先使用status字段
  if (details.status) {
    switch (details.status.toLowerCase()) {
      case 'failed':
        return '执行失败'
      case 'changed':
        return '执行成功（有变更）'
      case 'ok':
        return '执行成功（无变更）'
      default:
        return details.status.toUpperCase()
    }
  }

  // 兼容旧格式
  if (details.failed) return '执行失败'
  if (details.changed) return '执行成功（有变更）'
  return '执行成功（无变更）'
}

// 获取状态样式类
const getStatusClass = (details: any) => {
  // 优先使用status字段
  if (details.status) {
    switch (details.status.toLowerCase()) {
      case 'failed':
        return 'error-text'
      case 'changed':
        return 'warning-text'
      case 'ok':
        return 'success-text'
      default:
        return 'info-text'
    }
  }

  // 兼容旧格式
  if (details.failed) return 'error-text'
  if (details.changed) return 'warning-text'
  return 'success-text'
}

// 格式化任务详情
const formatTaskDetails = (details: any): string[] => {
  if (!details) return []

  const lines: string[] = []

  if (details.stdout) {
    lines.push('📤 标准输出:')
    lines.push(details.stdout)
  }

  if (details.stdout_lines && details.stdout_lines.length > 0) {
    lines.push('📋 输出行:')
    details.stdout_lines.forEach((line: string, index: number) => {
      lines.push(`  ${index + 1}. ${line}`)
    })
  }

  if (details.stderr) {
    lines.push('❌ 错误输出:')
    lines.push(details.stderr)
  }

  if (details.cmd) {
    lines.push(`💻 执行命令: ${details.cmd}`)
  }

  if (details.rc !== undefined) {
    lines.push(`🔢 返回码: ${details.rc}`)
  }

  if (details.delta) {
    lines.push(`⏱️ 执行时间: ${details.delta}`)
  }

  return lines
}

const formatTerminalLine = (content: any) => {
  // 确保content是字符串
  if (typeof content !== 'string') {
    content = String(content || '')
  }

  // Ansible输出着色
  return content
    .replace(/\[OK\]/g, '<span class="text-success">[OK]</span>')
    .replace(/\[CHANGED\]/g, '<span class="text-warning">[CHANGED]</span>')
    .replace(/\[FAILED\]/g, '<span class="text-error">[FAILED]</span>')
    .replace(/\[UNREACHABLE\]/g, '<span class="text-error">[UNREACHABLE]</span>')
    .replace(/TASK \[(.*?)\]/g, '<span class="text-info">TASK [$1]</span>')
    .replace(/PLAY \[(.*?)\]/g, '<span class="text-primary">PLAY [$1]</span>')
}

const clearTerminal = () => {
  terminalLines.value = []
  currentExecution.value = null
  executionProgress.value = 0
  currentTask.value = ''
  executionTime.value = ''
}

const copyOutput = () => {
  const output = terminalLines.value.map(line => `${line.timestamp} ${line.content}`).join('\n')
  navigator.clipboard.writeText(output).then(() => {
    ElMessage.success('输出已复制到剪贴板')
  }).catch(() => {
    ElMessage.error('复制失败')
  })
}

const downloadLog = () => {
  const output = terminalLines.value.map(line => `${line.timestamp} ${line.content}`).join('\n')
  const blob = new Blob([output], { type: 'text/plain' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `playbook-execution-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.log`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
}

const pauseExecution = () => {
  ElMessage.info('暂停功能开发中...')
}

const stopExecution = () => {
  if (currentExecution.value) {
    // TODO: 调用停止API
    executing.value = false
    addTerminalLine('⏹️ 执行已被用户停止', 'warning')
    ElMessage.warning('执行已停止')
  }
}

// 其他方法
const validatePlaybook = () => {
  validating.value = true
  syntaxStatus.value = { type: 'validating', message: '验证中...' }

  setTimeout(() => {
    validateSyntax()
    validating.value = false
    ElMessage.success('语法检查完成')
  }, 1000)
}

const savePlaybook = async () => {
  if (!activeFile.value || !editorInstance) {
    ElMessage.warning('没有可保存的文件')
    return
  }

  if (editMode.value === 'online') {
    ElMessage.info('在线编辑模式下，内容已自动保存到内存中')
    return
  }

  try {
    const content = editorInstance.getValue()
    const hostId = selectedAnsibleHost.value

    if (!hostId) {
      ElMessage.warning('请先选择目标主机')
      return
    }

    // 使用存储的完整文件路径
    const filePath = currentFilePath.value || (currentPath.value === '/'
      ? `/${activeFile.value}`
      : `${currentPath.value}/${activeFile.value}`)

    await ansibleAPI.saveFileContent(hostId, filePath, content)

    // 标记为未修改
    const file = playbookFiles.value.find(f => f.path === activeFile.value)
    if (file) {
      file.modified = false
    }

    ElMessage.success(`文件 ${activeFile.value} 保存成功`)
  } catch (error) {
    console.error('保存文件失败:', error)
    ElMessage.error('保存文件失败')
  }
}

const loadTemplate = () => {
  if (editorInstance) {
    editorInstance.setValue(getDefaultPlaybookContent())
    ElMessage.success('已加载默认模板')
  }
}

// 调试执行请求
const debugExecution = () => {
  const playbookContent = editorInstance?.getValue() || ''

  const requestData = {
    mode: editMode.value,
    playbook_content: playbookContent,
    credential_id: selectedCredential.value,
    inventory_id: selectedInventory.value,
    extra_vars: {}
  }

  console.log('=== 执行请求调试 ===')
  console.log('请求数据:', requestData)
  console.log('Playbook内容长度:', playbookContent.length)
  console.log('凭据ID:', selectedCredential.value)
  console.log('清单ID:', selectedInventory.value)

  ElMessage.info('执行请求调试信息已输出到Console')
}





// 辅助方法
const getSelectedCredentialName = () => {
  const cred = availableCredentials.value.find(c => c.id === selectedCredential.value)
  return cred ? `${cred.name} (${cred.credential_type_display})` : '未知凭据'
}

const getSelectedInventoryName = () => {
  const inv = inventories.value.find(i => i.id === selectedInventory.value)
  return inv ? inv.name : '未知清单'
}

const getSelectedConfigName = () => {
  const config = ansibleConfigs.value.find(c => c.id === selectedAnsibleConfig.value)
  return config ? config.name : '未知配置'
}

const getSelectedAnsibleHostName = () => {
  const host = ansibleHosts.value.find(h => h.id === selectedAnsibleHost.value)
  return host ? `${host.hostname} (${host.private_ip})` : '未知主机'
}

// 生命周期
onMounted(async () => {
  console.log('Playbook编辑执行页面已加载')

  // 初始化编辑器
  await nextTick()
  initializeEditor()

  // 加载初始数据 - 默认加载在线编辑模式数据
  await loadOnlineModeData()
})

onUnmounted(() => {
  // 清理编辑器
  if (editorInstance) {
    editorInstance.dispose()
  }

  // 清理自动完成提供者
  if (completionProviderDisposable) {
    completionProviderDisposable.dispose()
  }

  // 不需要清理内置YAML语言
  // unregisterAnsibleInventoryLanguage()

  // 清理事件监听器
  document.removeEventListener('mousemove', handleResize)
  document.removeEventListener('mouseup', stopResize)

  // 清理定时器
  if (validateTimeout) {
    clearTimeout(validateTimeout)
  }
})
</script>

<style lang="scss" scoped>
/* Playbook编辑执行页面样式 */
.playbook-execution-container {
  position: relative;
  min-height: 100vh;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(20, 20, 40, 0.95) 50%, rgba(0, 0, 0, 0.9) 100%);
  overflow: hidden;
}

.starry-background {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

.stars, .stars2, .stars3 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: transparent;
}

.stars {
  background-image: radial-gradient(2px 2px at 20px 30px, #eee, transparent), radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.8), transparent), radial-gradient(1px 1px at 90px 40px, #fff, transparent);
  background-repeat: repeat;
  background-size: 200px 100px;
  animation: zoom 20s infinite linear;
}

.stars2 {
  background-image: radial-gradient(1px 1px at 40px 60px, #fff, transparent), radial-gradient(1px 1px at 120px 10px, rgba(255,255,255,0.7), transparent);
  background-repeat: repeat;
  background-size: 300px 200px;
  animation: zoom 40s infinite linear;
}

.stars3 {
  background-image: radial-gradient(1px 1px at 10px 10px, rgba(255,255,255,0.5), transparent);
  background-repeat: repeat;
  background-size: 400px 300px;
  animation: zoom 60s infinite linear;
}

@keyframes zoom {
  from { transform: scale(1); }
  to { transform: scale(1.5); }
}

// 主要内容区域
.main-content {
  position: relative;
  z-index: 10;
  display: flex;
  height: calc(100vh - 180px);
  gap: 0;
  margin: 20px;
  margin-bottom: 60px;
}

.glass-effect {
  background: rgba(164, 244, 186, 0.1);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 12px;
  backdrop-filter: blur(20px);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.page-header {
  margin: 20px 20px 0 20px;
  padding: 25px 30px;
  position: relative;
  z-index: 10;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 30px;
}

.title-section {
  flex: 1;
}

.action-buttons {
  display: flex;
  gap: 10px;
}

.page-title {
  color: #00eaff;
  font-size: 2.5em;
  margin: 0 0 10px 0;
  text-shadow: 0 0 20px rgba(0, 234, 255, 0.5);
  display: flex;
  align-items: center;
  gap: 15px;

  i {
    font-size: 0.8em;
  }
}

.page-subtitle {
  color: rgba(255, 255, 255, 0.7);
  font-size: 1.1em;
  margin: 0;
}

// 左侧编辑器面板
.editor-panel {
  display: flex;
  flex-direction: column;
  min-width: 300px;

  .mode-switch-section {
    padding: 15px;
    border-bottom: 1px solid rgba(164, 244, 186, 0.2);
    display: flex;
    justify-content: center;

    .mode-switch {
      display: inline-flex;
      border-radius: 8px;
      overflow: hidden;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
      backdrop-filter: blur(10px);

      :deep(.el-radio-button) {
        margin: 0 !important;

        .el-radio-button__inner {
          background: rgba(164, 244, 186, 0.15) !important;
          border: 1px solid rgba(164, 244, 186, 0.3) !important;
          color: rgba(255, 255, 255, 0.9) !important;
          transition: all 0.3s ease !important;
          margin: 0 !important;
          border-radius: 0 !important;
          padding: 12px 24px !important;
          font-weight: 500 !important;
          font-size: 14px !important;

          i {
            margin-right: 8px !important;
            color: #00eaff !important;
          }

          &:hover {
            background: rgba(164, 244, 186, 0.25) !important;
            border-color: rgba(164, 244, 186, 0.5) !important;
            color: #ffffff !important;
            transform: translateY(-1px) !important;
          }
        }

        // 第一个按钮左侧圆角
        &:first-child .el-radio-button__inner {
          border-top-left-radius: 8px !important;
          border-bottom-left-radius: 8px !important;
          border-right: none !important;
        }

        // 最后一个按钮右侧圆角
        &:last-child .el-radio-button__inner {
          border-top-right-radius: 8px !important;
          border-bottom-right-radius: 8px !important;
          border-left: none !important;
        }

        &.is-active .el-radio-button__inner {
          background: rgba(34, 197, 94, 0.2) !important;
          border-color: rgba(34, 197, 94, 0.4) !important;
          color: #ffffff !important;
          box-shadow: 0 4px 16px rgba(34, 197, 94, 0.3) !important;
          transform: translateY(-1px) !important;

          i {
            color: #22c55e !important;
          }
        }
      }
    }
  }

  .online-mode, .existing-mode {
    // 模式特定样式可以在这里添加
  }

  .config-section {
    padding: 8px 15px;
    border-bottom: 1px solid rgba(164, 244, 186, 0.2);

    .config-form {
      display: flex;
      flex-wrap: wrap;
      gap: 15px;
      align-items: flex-end;

      .el-form-item {
        margin-bottom: 5px;
        flex: 1;
        min-width: 180px;

        .el-form-item__label {
          color: rgba(255, 255, 255, 0.8);
          font-size: 12px;
        }
      }

      .config-select {
        min-width: 250px;
      }

      .host-select, .credential-select, .inventory-select {
        min-width: 200px;
      }
    }

    .config-option, .host-option, .credential-option, .inventory-option {
      display: flex;
      align-items: center;
      gap: 8px;

      i {
        color: rgba(164, 244, 186, 0.8);
      }
    }
  }

  .directory-section {
    padding: 15px;
    border-bottom: 1px solid rgba(164, 244, 186, 0.2);

    .section-header {
      display: flex;
      align-items: center;
      gap: 8px;
      margin-bottom: 10px;
      color: rgba(255, 255, 255, 0.8);
      font-size: 13px;

      .refresh-btn {
        margin-left: auto;
        padding: 4px 8px;
        font-size: 12px;
      }
    }

    .directory-cascader {
      width: 100%;
    }
  }



  .editor-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 15px;
    background: rgba(164, 244, 186, 0.08);
    border-bottom: 1px solid rgba(164, 244, 186, 0.2);
    font-size: 12px;

    .toolbar-left {
      display: flex;
      align-items: center;

      .file-info {
        display: flex;
        align-items: center;
        gap: 6px;
        color: rgba(255, 255, 255, 0.8);
        font-weight: 500;

        i {
          color: rgba(164, 244, 186, 0.8);
        }
      }
    }

    .toolbar-right {
      display: flex;
      align-items: center;
      gap: 8px;
    }
  }

  .editor-container {
    flex: 1;
    max-height: calc(100vh - 380px); // 为选择现有模式的配置区域留出空间
    overflow: hidden;

    .monaco-editor {
      height: 100%;
    }
  }

  .editor-status {
    padding: 8px 15px;
    background: rgba(164, 244, 186, 0.1);
    font-size: 11px;
    display: flex;
    justify-content: space-between;
    border-top: 1px solid rgba(164, 244, 186, 0.2);

    .status-left, .status-right {
      display: flex;
      align-items: center;
      gap: 8px;
      color: rgba(255, 255, 255, 0.7);
    }

    .separator {
      color: rgba(164, 244, 186, 0.5);
    }

    .syntax-status {
      display: flex;
      align-items: center;
      gap: 4px;

      &.ready {
        color: #51cf66;
      }

      &.error {
        color: #ff6b6b;
      }

      &.warning {
        color: #ffd43b;
      }

      &.validating {
        color: #74c0fc;
      }
    }
  }
}

// 分隔条
.resizer {
  width: 4px;
  background: rgba(164, 244, 186, 0.3);
  cursor: col-resize;
  transition: background 0.2s;
  position: relative;

  &:hover {
    background: rgba(164, 244, 186, 0.6);
  }

  &::before {
    content: '';
    position: absolute;
    left: -2px;
    right: -2px;
    top: 0;
    bottom: 0;
  }
}

// 右侧终端面板
.terminal-panel {
  display: flex;
  flex-direction: column;
  min-width: 300px;

  .terminal-header {
    padding: 15px;
    border-bottom: 1px solid rgba(164, 244, 186, 0.2);
    display: flex;
    justify-content: space-between;
    align-items: center;

    .terminal-title {
      display: flex;
      align-items: center;
      gap: 8px;
      color: rgba(255, 255, 255, 0.8);
      font-size: 14px;
      font-weight: 500;

      .execution-status {
        margin-left: 10px;
      }
    }

    .terminal-controls {
      display: flex;
      gap: 5px;

      .control-btn {
        padding: 4px 8px;
        font-size: 12px;
        min-width: auto;
      }
    }
  }

  .execution-progress {
    padding: 10px 15px;
    border-bottom: 1px solid rgba(164, 244, 186, 0.2);

    .progress-bar {
      margin-bottom: 8px;
    }

    .progress-info {
      display: flex;
      justify-content: space-between;
      font-size: 12px;
      color: rgba(255, 255, 255, 0.7);

      .current-task {
        flex: 1;
        margin-right: 10px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .execution-time {
        color: rgba(164, 244, 186, 0.8);
      }
    }
  }

  .terminal-output {
    flex: 1;
    padding: 15px;
    overflow-y: auto;
    font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
    font-size: 12px;
    line-height: 1.4;
    background: rgba(0, 0, 0, 0.3);

    .terminal-line {
      margin-bottom: 4px;
      padding: 2px 0;
      display: flex;
      align-items: center;
      position: relative;
      line-height: 1.4;

      .timestamp {
        color: rgba(164, 244, 186, 0.6);
        margin-right: 8px;
        font-size: 11px;
        min-width: 70px;
        flex-shrink: 0;
      }

      .content {
        flex: 1;
        word-break: break-all;
      }

      .click-hint {
        margin-left: 8px;
        color: rgba(164, 244, 186, 0.6);
        font-size: 10px;
        flex-shrink: 0;
      }

      // 可点击行样式
      &.clickable {
        cursor: pointer;
        padding: 2px 4px;
        border-radius: 3px;
        transition: all 0.2s ease;

        &:hover {
          background: rgba(164, 244, 186, 0.1);

          .click-hint {
            color: rgba(164, 244, 186, 1);
          }
        }
      }

      // 详情行样式
      &.detail-line {
        margin-left: 20px;
        padding-left: 10px;
        border-left: 2px solid rgba(164, 244, 186, 0.3);
        background: rgba(0, 0, 0, 0.2);

        .content {
          color: rgba(255, 255, 255, 0.7);
          font-size: 11px;
        }
      }

      &.output .content {
        color: rgba(255, 255, 255, 0.9) !important;
      }

      &.error .content {
        color: #ff6b6b !important;
        font-weight: 500;
      }

      &.success .content {
        color: #51cf66 !important;
        font-weight: 500;
      }

      &.warning .content {
        color: #ffd43b !important;
        font-weight: 500;
      }

      &.info .content {
        color: #74c0fc !important;
      }
    }

    .terminal-empty {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;
      color: rgba(255, 255, 255, 0.5);
      text-align: center;

      i {
        font-size: 48px;
        margin-bottom: 20px;
        color: rgba(164, 244, 186, 0.3);
      }

      p {
        margin: 5px 0;

        &.hint {
          font-size: 12px;
          color: rgba(255, 255, 255, 0.3);
        }
      }
    }

    // 滚动条样式
    &::-webkit-scrollbar {
      width: 6px;
    }

    &::-webkit-scrollbar-track {
      background: rgba(164, 244, 186, 0.1);
    }

    &::-webkit-scrollbar-thumb {
      background: rgba(164, 244, 186, 0.3);
      border-radius: 3px;

      &:hover {
        background: rgba(164, 244, 186, 0.5);
      }
    }
  }
}

// 终端输出着色
.terminal-output {
  :deep(.text-success) {
    color: #51cf66;
    font-weight: 500;
  }

  :deep(.text-warning) {
    color: #ffd43b;
    font-weight: 500;
  }

  :deep(.text-error) {
    color: #ff6b6b;
    font-weight: 500;
  }

  :deep(.text-info) {
    color: #74c0fc;
    font-weight: 500;
  }

  :deep(.text-primary) {
    color: #00eaff;
    font-weight: 600;
  }
}



// 响应式设计
@media (max-width: 1200px) {
  .main-content {
    flex-direction: column;
    height: auto;
  }

  .editor-panel, .terminal-panel {
    width: 100% !important;
    min-height: 400px;
  }

  .resizer {
    display: none;
  }

  .header-content {
    flex-direction: column;
    gap: 20px;
    text-align: center;
  }

  .action-buttons {
    justify-content: center;
    flex-wrap: wrap;
  }
}

@media (max-width: 768px) {
  .page-header {
    margin: 10px;
    padding: 20px;
  }

  .main-content {
    margin: 10px;
  }

  .config-form {
    .el-form-item {
      display: block;
      margin-bottom: 15px;

      .el-form-item__label {
        display: block;
        margin-bottom: 5px;
      }

      .el-form-item__content {
        margin-left: 0 !important;
      }
    }

    .config-select, .host-select, .credential-select, .inventory-select {
      width: 100% !important;
      min-width: 200px !important;
    }
  }

  .action-buttons {
    gap: 5px;
  }
}
/* Monaco编辑器语法高亮样式优化 */
:deep(.monaco-editor) {
  /* 确保语法高亮不被覆盖 */
  .mtk1 { color: #D4D4D4 !important; }
  .mtk2 { color: #6A9955 !important; font-style: italic !important; }
  .mtk3 { color: #00D7FF !important; font-weight: bold !important; }
  .mtk4 { color: #4FC1FF !important; font-weight: bold !important; }
  .mtk5 { color: #FFD700 !important; }
  .mtk6 { color: #FFA500 !important; }
  .mtk7 { color: #00FF7F !important; }
  .mtk8 { color: #87CEEB !important; }
  .mtk9 { color: #DA70D6 !important; font-weight: bold !important; }
  .mtk10 { color: #40E0D0 !important; }

  /* 智能提示样式 */
  .suggest-widget {
    background: rgba(37, 37, 38, 0.95) !important;
    border: 1px solid rgba(69, 69, 69, 0.8) !important;
    border-radius: 6px !important;
    backdrop-filter: blur(10px) !important;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3) !important;
    z-index: 9999 !important;
  }

  .suggest-widget .monaco-list .monaco-list-row {
    background: transparent !important;
    color: #CCCCCC !important;
  }

  .suggest-widget .monaco-list .monaco-list-row:hover {
    background: rgba(164, 244, 186, 0.2) !important;
  }

  .suggest-widget .monaco-list .monaco-list-row.focused {
    background: rgba(164, 244, 186, 0.3) !important;
  }

  .suggest-widget .suggest-icon {
    opacity: 0.8 !important;
  }
}

// AWX风格任务详情对话框样式
.task-details-dialog {
  .el-dialog__body {
    padding: 20px;
    max-height: 80vh;
    overflow-y: auto;
  }

  .scrollable-content {
    max-height: 75vh;
    overflow-y: auto;
  }

  .output-box {
    max-height: 300px;
    overflow-y: auto;
    margin-bottom: 15px;
    border: 1px solid rgba(164, 244, 186, 0.3);
    border-radius: 6px;
  }

  .task-details-content {
    .detail-section {
      margin-bottom: 20px;

      h4 {
        color: #a4f4ba;
        margin-bottom: 10px;
        font-size: 14px;
        font-weight: bold;
        border-bottom: 1px solid rgba(164, 244, 186, 0.3);
        padding-bottom: 5px;
      }

      .detail-item {
        margin-bottom: 8px;
        font-size: 13px;

        strong {
          color: #a4f4ba;
          margin-right: 8px;
        }
      }

      .success-text {
        color: #51cf66;
      }

      .warning-text {
        color: #ffd43b;
      }

      .error-text {
        color: #ff6b6b;
      }

      .output-content, .error-content {
        background: rgba(0, 0, 0, 0.4);
        border: 1px solid rgba(164, 244, 186, 0.3);
        border-radius: 4px;
        padding: 12px;
        font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
        white-space: pre-wrap;
        word-break: break-word;
        max-height: 400px;
        overflow-y: auto;
        font-size: 12px;
        line-height: 1.4;
      }

      .error-output {
        border-color: rgba(255, 107, 107, 0.3);
        color: #ff6b6b;
      }

      .json-content {
        font-size: 12px;
        line-height: 1.4;
        color: #a4f4ba;
        white-space: pre-wrap;
        word-break: break-all;
        max-height: 200px;
        overflow-y: auto;
      }

      .error-content {
        color: #ff6b6b;
        border-color: rgba(255, 107, 107, 0.3);
      }

      .output-lines {
        background: rgba(40, 167, 69, 0.1);
        border-left: 4px solid #28a745;
        padding: 15px;
        border-radius: 4px;
        font-family: 'Courier New', monospace;
        max-height: 200px;
        overflow-y: auto;
      }

      .output-line {
        margin: 2px 0;
        color: #28a745;
      }

      .info-message {
        display: flex;
        align-items: center;
        margin-bottom: 15px;
        padding: 10px;
        background: rgba(40, 167, 69, 0.1);
        border-radius: 4px;
        border-left: 4px solid #28a745;
      }

      .success-icon {
        color: #28a745;
        margin-right: 10px;
        font-size: 16px;
      }

      .result-explanation {
        margin: 0;
        padding-left: 20px;
        color: #6c757d;
      }

      .result-explanation li {
        margin: 5px 0;
        color: #495057;
      }

      .explanation-title {
        font-weight: bold;
        color: #28a745;
        margin-bottom: 8px;
      }

      .stdout-lines {
        background: rgba(0, 0, 0, 0.4);
        border: 1px solid rgba(164, 244, 186, 0.3);
        border-radius: 4px;
        max-height: 300px;
        overflow-y: auto;

        .stdout-line {
          display: flex;
          padding: 4px 12px;
          font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
          font-size: 12px;
          line-height: 1.4;
          border-bottom: 1px solid rgba(164, 244, 186, 0.1);

          &:hover {
            background: rgba(164, 244, 186, 0.05);
          }

          .line-number {
            color: rgba(164, 244, 186, 0.6);
            margin-right: 12px;
            min-width: 30px;
            text-align: right;
            flex-shrink: 0;
          }

          .line-content {
            color: rgba(255, 255, 255, 0.9);
            flex: 1;
            word-break: break-all;
          }
        }
      }
    }
  }
}

/* 工具栏按钮样式 - 和Inventory页面保持一致 */
.glass-button {
  background: rgba(164, 244, 186, 0.15) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: rgba(255, 255, 255, 0.9) !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(10px) !important;
  border-radius: 8px !important;
  padding: 8px 16px !important;
  font-size: 14px !important;
  font-weight: 500 !important;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important;

  &:hover {
    background: rgba(164, 244, 186, 0.25) !important;
    border-color: rgba(164, 244, 186, 0.5) !important;
    color: #ffffff !important;
    transform: translateY(-2px) !important;
    box-shadow: 0 4px 16px rgba(164, 244, 186, 0.2) !important;
  }

  i {
    margin-right: 6px !important;
    color: #00eaff !important;
  }

  /* 刷新按钮 - 紫色 */
  &.refresh-button {
    background: rgba(138, 43, 226, 0.2) !important;
    border-color: rgba(138, 43, 226, 0.4) !important;
    color: #ffffff !important;

    &:hover {
      background: rgba(138, 43, 226, 0.3) !important;
      border-color: rgba(138, 43, 226, 0.6) !important;
      box-shadow: 0 4px 16px rgba(138, 43, 226, 0.3) !important;
    }

    i {
      color: #8a2be2 !important;
    }
  }

  /* 同步按钮 - 蓝色 */
  &.sync-button {
    background: rgba(59, 130, 246, 0.2) !important;
    border-color: rgba(59, 130, 246, 0.4) !important;
    color: #ffffff !important;

    &:hover {
      background: rgba(59, 130, 246, 0.3) !important;
      border-color: rgba(59, 130, 246, 0.6) !important;
      box-shadow: 0 4px 16px rgba(59, 130, 246, 0.3) !important;
    }

    i {
      color: #3b82f6 !important;
    }
  }

  /* 添加按钮 - 绿色 */
  &.add-button {
    background: rgba(34, 197, 94, 0.2) !important;
    border-color: rgba(34, 197, 94, 0.4) !important;
    color: #ffffff !important;

    &:hover {
      background: rgba(34, 197, 94, 0.3) !important;
      border-color: rgba(34, 197, 94, 0.6) !important;
      box-shadow: 0 4px 16px rgba(34, 197, 94, 0.3) !important;
    }

    i {
      color: #22c55e !important;
    }
  }

  /* 导入按钮 - 青色 */
  &.import-button {
    background: rgba(6, 182, 212, 0.2) !important;
    border-color: rgba(6, 182, 212, 0.4) !important;
    color: #ffffff !important;

    &:hover {
      background: rgba(6, 182, 212, 0.3) !important;
      border-color: rgba(6, 182, 212, 0.6) !important;
      box-shadow: 0 4px 16px rgba(6, 182, 212, 0.3) !important;
    }

    i {
      color: #06b6d4 !important;
    }
  }

  /* 导出按钮 - 橙色 */
  &.export-button {
    background: rgba(255, 165, 0, 0.2) !important;
    border-color: rgba(255, 165, 0, 0.4) !important;
    color: #ffffff !important;

    &:hover {
      background: rgba(255, 165, 0, 0.3) !important;
      border-color: rgba(255, 165, 0, 0.6) !important;
      box-shadow: 0 4px 16px rgba(255, 165, 0, 0.3) !important;
    }

    i {
      color: #ffa500 !important;
    }
  }

  /* 智能同步按钮 - 粉色 */
  &.smart-button {
    background: rgba(236, 72, 153, 0.2) !important;
    border-color: rgba(236, 72, 153, 0.4) !important;
    color: #ffffff !important;

    &:hover {
      background: rgba(236, 72, 153, 0.3) !important;
      border-color: rgba(236, 72, 153, 0.6) !important;
      box-shadow: 0 4px 16px rgba(236, 72, 153, 0.3) !important;
    }

    i {
      color: #ec4899 !important;
    }
  }
}

/* 目录选择弹窗样式 */
:deep(.directory-dialog) {
  .el-dialog {
    background: rgba(20, 20, 40, 0.95) !important;
    border: 1px solid rgba(164, 244, 186, 0.3) !important;
    border-radius: 12px !important;
    backdrop-filter: blur(15px) !important;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3) !important;
    z-index: 2000 !important;
  }

  .el-dialog__header {
    background: rgba(164, 244, 186, 0.1) !important;
    border-bottom: 1px solid rgba(164, 244, 186, 0.2) !important;
    border-radius: 12px 12px 0 0 !important;
    padding: 20px !important;

    .el-dialog__title {
      color: rgba(255, 255, 255, 0.9) !important;
      font-size: 18px !important;
      font-weight: 600 !important;
    }
  }

  .el-dialog__body {
    padding: 0 !important;
    background: transparent !important;
  }

  .el-dialog__footer {
    background: rgba(164, 244, 186, 0.05) !important;
    border-top: 1px solid rgba(164, 244, 186, 0.2) !important;
    border-radius: 0 0 12px 12px !important;
    padding: 20px !important;
  }
}

.directory-browser {
  padding: 20px;

  .current-path {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 15px;
    background: rgba(164, 244, 186, 0.08) !important;
    border: 1px solid rgba(164, 244, 186, 0.2) !important;
    border-radius: 8px !important;
    margin-bottom: 20px;
    backdrop-filter: blur(10px) !important;

    .path-input-section {
      flex: 1;
      margin-right: 15px;

      .path-input-wrapper {
        display: flex;
        align-items: center;
        gap: 10px;

        .path-icon {
          color: #00eaff !important;
          font-size: 16px;
          flex-shrink: 0;
        }

        .path-input {
          flex: 1;

          :deep(.el-input__wrapper) {
            background: rgba(164, 244, 186, 0.1) !important;
            border: 1px solid rgba(164, 244, 186, 0.3) !important;
            border-radius: 6px !important;
            box-shadow: none !important;
            backdrop-filter: blur(5px) !important;
          }

          :deep(.el-input__inner) {
            color: rgba(255, 255, 255, 0.9) !important;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            font-weight: 500;
            background: transparent !important;

            &::placeholder {
              color: rgba(255, 255, 255, 0.5) !important;
            }
          }

          :deep(.el-input__wrapper:hover) {
            border-color: rgba(164, 244, 186, 0.5) !important;
          }

          :deep(.el-input__wrapper.is-focus) {
            border-color: #00eaff !important;
            box-shadow: 0 0 0 2px rgba(0, 234, 255, 0.2) !important;
          }
        }
      }
    }

    .path-actions {
      display: flex;
      gap: 10px;
      flex-shrink: 0;
    }
  }

  .directory-content {
    min-height: 300px;
    max-height: 500px;
    overflow-y: auto;

    .section-title {
      color: rgba(255, 255, 255, 0.8) !important;
      font-size: 14px;
      font-weight: 600;
      margin: 20px 0 10px 0;
      display: flex;
      align-items: center;
      gap: 8px;

      i {
        color: #00eaff !important;
      }
    }

    .yaml-file-selector {
      margin: 15px 0;

      .yaml-select {
        width: 100%;

        :deep(.el-select) {
          width: 100%;
        }

        :deep(.el-input__wrapper) {
          background: rgba(164, 244, 186, 0.1) !important;
          border: 1px solid rgba(164, 244, 186, 0.3) !important;
          border-radius: 6px !important;
          box-shadow: none !important;
          backdrop-filter: blur(5px) !important;
        }

        :deep(.el-input__inner) {
          color: rgba(255, 255, 255, 0.9) !important;
          background: transparent !important;

          &::placeholder {
            color: rgba(255, 255, 255, 0.5) !important;
          }
        }

        :deep(.el-input__wrapper:hover) {
          border-color: rgba(164, 244, 186, 0.5) !important;
        }

        :deep(.el-input__wrapper.is-focus) {
          border-color: #00eaff !important;
          box-shadow: 0 0 0 2px rgba(0, 234, 255, 0.2) !important;
        }

        :deep(.el-select__caret) {
          color: rgba(255, 255, 255, 0.7) !important;
        }
      }
    }

    .yaml-option {
      display: flex;
      align-items: center;
      gap: 8px;

      i {
        color: #00eaff !important;
        font-size: 14px;
      }

      span {
        color: rgba(255, 255, 255, 0.9) !important;
      }
    }

    .directory-list, .file-list {
      display: grid;
      gap: 8px;
    }

    .directory-item, .file-item {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 12px 15px;
      background: rgba(164, 244, 186, 0.05) !important;
      border: 1px solid rgba(164, 244, 186, 0.15) !important;
      border-radius: 6px !important;
      cursor: pointer;
      transition: all 0.3s ease !important;

      &:hover {
        background: rgba(164, 244, 186, 0.15) !important;
        border-color: rgba(164, 244, 186, 0.3) !important;
        transform: translateY(-1px) !important;
      }

      i {
        color: #00eaff !important;
        font-size: 16px;
        width: 20px;
        text-align: center;
      }

      span {
        color: rgba(255, 255, 255, 0.9) !important;
        flex: 1;
      }

      .file-size {
        color: rgba(255, 255, 255, 0.6) !important;
        font-size: 12px;
        margin-left: auto;
      }

      .fa-chevron-right {
        color: rgba(164, 244, 186, 0.6) !important;
        font-size: 12px;
        margin-left: auto;
      }
    }

    .file-item.selected {
      background: rgba(34, 197, 94, 0.2) !important;
      border-color: rgba(34, 197, 94, 0.4) !important;

      i {
        color: #22c55e !important;
      }
    }

    .empty-state, .loading-state {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding: 60px 20px;
      color: rgba(255, 255, 255, 0.6) !important;

      i {
        font-size: 48px;
        margin-bottom: 15px;
        color: rgba(164, 244, 186, 0.4) !important;
      }

      p {
        font-size: 16px;
        margin: 0;
      }
    }

    .loading-state i {
      color: #00eaff !important;
    }
  }
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 修复下拉菜单z-index问题 */
:deep(.el-select-dropdown) {
  z-index: 3000 !important;
}

:deep(.el-popper) {
  z-index: 3000 !important;
}
</style>
